0.2.0 #71
@ -1,4 +1,8 @@
|
|||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import react.child
|
import react.child
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
@ -17,6 +21,7 @@ import space.kscience.visionforge.solid.*
|
|||||||
import space.kscience.visionforge.startApplication
|
import space.kscience.visionforge.startApplication
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
import kotlin.math.sqrt
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
private class JsPlaygroundApp : Application {
|
private class JsPlaygroundApp : Application {
|
||||||
@ -31,9 +36,38 @@ private class JsPlaygroundApp : Application {
|
|||||||
|
|
||||||
val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page")
|
val element = document.getElementById("playground") ?: error("Element with id 'playground' not found on page")
|
||||||
|
|
||||||
|
val bouncingSphere = SolidGroup {
|
||||||
|
sphere(5.0, "ball") {
|
||||||
|
detail = 16
|
||||||
|
color("red")
|
||||||
|
val h = 100.0
|
||||||
|
y = h
|
||||||
|
GlobalScope.launch {
|
||||||
|
val g = 10.0
|
||||||
|
val dt = 0.1
|
||||||
|
var time = 0.0
|
||||||
|
var velocity = 0.0
|
||||||
|
while (isActive) {
|
||||||
|
delay(20)
|
||||||
|
time += dt
|
||||||
|
velocity -= g * dt
|
||||||
|
y = y.toDouble() + velocity * dt
|
||||||
|
if (y.toDouble() <= 2.5){
|
||||||
|
velocity = sqrt(2*g*h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box(200, 5, 200, name = "floor"){
|
||||||
|
y = -2.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val visionOfD0 = GdmlShowCase.babyIaxo().toVision()
|
val visionOfD0 = GdmlShowCase.babyIaxo().toVision()
|
||||||
|
|
||||||
val random = Random(112233)
|
val random = Random(112233)
|
||||||
|
|
||||||
val visionOfSpheres = SolidGroup {
|
val visionOfSpheres = SolidGroup {
|
||||||
repeat(100) {
|
repeat(100) {
|
||||||
sphere(5, name = "sphere[$it]") {
|
sphere(5, name = "sphere[$it]") {
|
||||||
@ -56,7 +90,16 @@ private class JsPlaygroundApp : Application {
|
|||||||
height = 100.vh
|
height = 100.vh
|
||||||
width = 100.vw
|
width = 100.vw
|
||||||
}
|
}
|
||||||
SmartTabs("D0") {
|
SmartTabs("gravity") {
|
||||||
|
Tab("gravity") {
|
||||||
|
child(ThreeCanvasWithControls) {
|
||||||
|
attrs {
|
||||||
|
context = playgroundContext
|
||||||
|
solid = bouncingSphere
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Tab("D0") {
|
Tab("D0") {
|
||||||
child(ThreeCanvasWithControls) {
|
child(ThreeCanvasWithControls) {
|
||||||
attrs {
|
attrs {
|
||||||
@ -73,8 +116,8 @@ private class JsPlaygroundApp : Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tab("plotly"){
|
Tab("plotly") {
|
||||||
Plotly{
|
Plotly {
|
||||||
attrs {
|
attrs {
|
||||||
context = playgroundContext
|
context = playgroundContext
|
||||||
plot = space.kscience.plotly.Plotly.plot {
|
plot = space.kscience.plotly.Plotly.plot {
|
||||||
|
@ -66,7 +66,7 @@ public val CanvasControls: FunctionComponent<CanvasControlsProps> = functionalCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = props.canvasOptions,
|
ownProperties = props.canvasOptions.meta,
|
||||||
allProperties = props.canvasOptions.meta.withDefault(Canvas3DOptions.descriptor.defaultNode),
|
allProperties = props.canvasOptions.meta.withDefault(Canvas3DOptions.descriptor.defaultNode),
|
||||||
descriptor = Canvas3DOptions.descriptor,
|
descriptor = Canvas3DOptions.descriptor,
|
||||||
expanded = false
|
expanded = false
|
||||||
|
@ -4,10 +4,13 @@ import org.w3c.dom.Element
|
|||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.Vision
|
||||||
|
import space.kscience.visionforge.computeProperties
|
||||||
|
import space.kscience.visionforge.getStyle
|
||||||
import space.kscience.visionforge.react.metaViewer
|
import space.kscience.visionforge.react.metaViewer
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
import space.kscience.visionforge.react.propertyEditor
|
||||||
import space.kscience.visionforge.solid.SolidReference
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
|
import space.kscience.visionforge.styles
|
||||||
|
|
||||||
public fun RBuilder.visionPropertyEditor(
|
public fun RBuilder.visionPropertyEditor(
|
||||||
vision: Vision,
|
vision: Vision,
|
||||||
@ -19,7 +22,6 @@ public fun RBuilder.visionPropertyEditor(
|
|||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = vision.meta,
|
ownProperties = vision.meta,
|
||||||
allProperties = vision.computeProperties(),
|
allProperties = vision.computeProperties(),
|
||||||
updateFlow = vision.propertyChanges,
|
|
||||||
descriptor = descriptor,
|
descriptor = descriptor,
|
||||||
key = key
|
key = key
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,6 @@ import react.dom.attrs
|
|||||||
import react.dom.option
|
import react.dom.option
|
||||||
import react.dom.select
|
import react.dom.select
|
||||||
import react.functionalComponent
|
import react.functionalComponent
|
||||||
import react.useState
|
|
||||||
import space.kscience.dataforge.meta.descriptors.allowedValues
|
import space.kscience.dataforge.meta.descriptors.allowedValues
|
||||||
import space.kscience.dataforge.values.asValue
|
import space.kscience.dataforge.values.asValue
|
||||||
import space.kscience.dataforge.values.string
|
import space.kscience.dataforge.values.string
|
||||||
@ -18,19 +17,16 @@ import space.kscience.dataforge.values.string
|
|||||||
@JsExport
|
@JsExport
|
||||||
public val MultiSelectChooser: FunctionComponent<ValueChooserProps> =
|
public val MultiSelectChooser: FunctionComponent<ValueChooserProps> =
|
||||||
functionalComponent("MultiSelectChooser") { props ->
|
functionalComponent("MultiSelectChooser") { props ->
|
||||||
var selectedItems by useState { props.item?.value?.list ?: emptyList() }
|
|
||||||
|
|
||||||
val onChange: (Event) -> Unit = { event: Event ->
|
val onChange: (Event) -> Unit = { event: Event ->
|
||||||
val newSelected = (event.target as HTMLSelectElement).selectedOptions.asList()
|
val newSelected = (event.target as HTMLSelectElement).selectedOptions.asList()
|
||||||
.map { (it as HTMLOptionElement).value.asValue() }
|
.map { (it as HTMLOptionElement).value.asValue() }
|
||||||
props.valueChanged?.invoke(newSelected.asValue())
|
props.meta.value = newSelected.asValue()
|
||||||
selectedItems = newSelected
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
attrs {
|
attrs {
|
||||||
multiple = true
|
multiple = true
|
||||||
values = selectedItems.mapTo(HashSet()) { it.string }
|
values = (props.actual.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
|
||||||
onChangeFunction = onChange
|
onChangeFunction = onChange
|
||||||
}
|
}
|
||||||
props.descriptor?.allowedValues?.forEach { optionValue ->
|
props.descriptor?.allowedValues?.forEach { optionValue ->
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
package space.kscience.visionforge.react
|
package space.kscience.visionforge.react
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import kotlinx.css.properties.TextDecoration
|
import kotlinx.css.properties.TextDecoration
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
@ -22,7 +13,6 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
|||||||
import space.kscience.dataforge.meta.descriptors.ValueRequirement
|
import space.kscience.dataforge.meta.descriptors.ValueRequirement
|
||||||
import space.kscience.dataforge.meta.descriptors.get
|
import space.kscience.dataforge.meta.descriptors.get
|
||||||
import space.kscience.dataforge.names.*
|
import space.kscience.dataforge.names.*
|
||||||
import space.kscience.dataforge.values.Value
|
|
||||||
import space.kscience.visionforge.hidden
|
import space.kscience.visionforge.hidden
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledButton
|
import styled.styledButton
|
||||||
@ -32,17 +22,17 @@ import styled.styledSpan
|
|||||||
public external interface PropertyEditorProps : RProps {
|
public external interface PropertyEditorProps : RProps {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root config object - always non null
|
* Root config object - always non-null
|
||||||
*/
|
*/
|
||||||
public var ownProperties: MutableMetaProvider
|
public var meta: ObservableMutableMeta
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide default item (greyed out if used)
|
* Provide default item (greyed out if used)
|
||||||
*/
|
*/
|
||||||
public var allProperties: MetaProvider?
|
public var withDefault: MetaProvider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full path to the displayed node in [ownProperties]. Could be empty
|
* Full path to the displayed node in [meta]. Could be empty
|
||||||
*/
|
*/
|
||||||
public var name: Name
|
public var name: Name
|
||||||
|
|
||||||
@ -51,16 +41,6 @@ public external interface PropertyEditorProps : RProps {
|
|||||||
*/
|
*/
|
||||||
public var descriptor: MetaDescriptor?
|
public var descriptor: MetaDescriptor?
|
||||||
|
|
||||||
/**
|
|
||||||
* A coroutine scope for updates
|
|
||||||
*/
|
|
||||||
public var scope: CoroutineScope?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flow names of updated properties
|
|
||||||
*/
|
|
||||||
public var updateFlow: Flow<Name>?
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial expanded state
|
* Initial expanded state
|
||||||
*/
|
*/
|
||||||
@ -68,54 +48,17 @@ public external interface PropertyEditorProps : RProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val PropertyEditorItem: FunctionComponent<PropertyEditorProps> =
|
private val PropertyEditorItem: FunctionComponent<PropertyEditorProps> =
|
||||||
functionalComponent("ConfigEditorItem") { props ->
|
functionalComponent("PropertyEditorItem") { props ->
|
||||||
propertyEditorItem(props)
|
propertyEditorItem(props)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
||||||
var expanded: Boolean by useState { props.expanded ?: true }
|
var expanded: Boolean by useState { props.expanded ?: true }
|
||||||
val descriptor: MetaDescriptor? = props.descriptor?.get(props.name)
|
val descriptor: MetaDescriptor? = useMemo(props.descriptor, props.name) { props.descriptor?.get(props.name) }
|
||||||
var ownProperty: Meta? by useState { props.ownProperties.getMeta(props.name) }
|
var ownProperty: ObservableMutableMeta by useState { props.meta.getOrCreate(props.name) }
|
||||||
val actualMeta = props.allProperties?.getMeta(props.name)
|
|
||||||
|
|
||||||
val token = props.name.lastOrNull()?.toString() ?: "Properties"
|
val keys = useMemo(descriptor) {
|
||||||
|
buildSet {
|
||||||
fun update() {
|
|
||||||
ownProperty = props.ownProperties.getMeta(props.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.updateFlow != null) {
|
|
||||||
useEffect(props.ownProperties, props.updateFlow) {
|
|
||||||
val updateJob = props.updateFlow!!.onEach { updatedName ->
|
|
||||||
if (updatedName == props.name) {
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
}.launchIn(props.scope ?: GlobalScope)
|
|
||||||
cleanup {
|
|
||||||
updateJob.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val expanderClick: (Event) -> Unit = {
|
|
||||||
expanded = !expanded
|
|
||||||
}
|
|
||||||
|
|
||||||
val valueChanged: (Value?) -> Unit = {
|
|
||||||
if (it == null) {
|
|
||||||
props.ownProperties.remove(props.name)
|
|
||||||
} else {
|
|
||||||
props.ownProperties.setValue(props.name, it)
|
|
||||||
}
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
val removeClick: (Event) -> Unit = {
|
|
||||||
props.ownProperties.remove(props.name)
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
val keys = buildSet {
|
|
||||||
descriptor?.children?.filterNot {
|
descriptor?.children?.filterNot {
|
||||||
it.key.startsWith("@") || it.value.hidden
|
it.key.startsWith("@") || it.value.hidden
|
||||||
}?.forEach {
|
}?.forEach {
|
||||||
@ -123,12 +66,41 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
}
|
}
|
||||||
//ownProperty?.items?.keys?.filterNot { it.body.startsWith("@") }?.let { addAll(it) }
|
//ownProperty?.items?.keys?.filterNot { it.body.startsWith("@") }?.let { addAll(it) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val token = props.name.lastOrNull()?.toString() ?: "Properties"
|
||||||
|
|
||||||
|
fun update() {
|
||||||
|
ownProperty = props.meta.getOrCreate(props.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(props.meta) {
|
||||||
|
props.meta.onChange(props) { updatedName ->
|
||||||
|
if (updatedName == props.name) {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup {
|
||||||
|
props.meta.removeListener(props)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val expanderClick: (Event) -> Unit = {
|
||||||
|
expanded = !expanded
|
||||||
|
}
|
||||||
|
|
||||||
|
val removeClick: (Event) -> Unit = {
|
||||||
|
props.meta.remove(props.name)
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
flexRow {
|
flexRow {
|
||||||
css {
|
css {
|
||||||
alignItems = Align.center
|
alignItems = Align.center
|
||||||
}
|
}
|
||||||
if(keys.isNotEmpty()) {
|
if (keys.isNotEmpty()) {
|
||||||
styledSpan {
|
styledSpan {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeCaret
|
+TreeStyles.treeCaret
|
||||||
@ -144,25 +116,26 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
styledSpan {
|
styledSpan {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeLabel
|
+TreeStyles.treeLabel
|
||||||
if (ownProperty == null) {
|
if (ownProperty.isEmpty()) {
|
||||||
+TreeStyles.treeLabelInactive
|
+TreeStyles.treeLabelInactive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+token
|
+token
|
||||||
}
|
}
|
||||||
if(!props.name.isEmpty() && descriptor?.valueRequirement != ValueRequirement.ABSENT) {
|
if (!props.name.isEmpty() && descriptor?.valueRequirement != ValueRequirement.ABSENT) {
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
//+TreeStyles.resizeableInput
|
//+TreeStyles.resizeableInput
|
||||||
width = 160.px
|
width = 160.px
|
||||||
margin(1.px, 5.px)
|
margin(1.px, 5.px)
|
||||||
}
|
}
|
||||||
valueChooser(
|
ValueChooser{
|
||||||
props.name,
|
attrs {
|
||||||
actualMeta,
|
this.descriptor = descriptor
|
||||||
descriptor,
|
this.meta = ownProperty
|
||||||
valueChanged
|
this.actual = props.withDefault.getMeta(props.name) ?: ownProperty
|
||||||
)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
styledButton {
|
styledButton {
|
||||||
@ -184,7 +157,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
}
|
}
|
||||||
+"\u00D7"
|
+"\u00D7"
|
||||||
attrs {
|
attrs {
|
||||||
if (ownProperty == null) {
|
if (ownProperty.isEmpty()) {
|
||||||
disabled = true
|
disabled = true
|
||||||
} else {
|
} else {
|
||||||
onClickFunction = removeClick
|
onClickFunction = removeClick
|
||||||
@ -206,8 +179,8 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
child(PropertyEditorItem) {
|
child(PropertyEditorItem) {
|
||||||
attrs {
|
attrs {
|
||||||
this.key = props.name.toString()
|
this.key = props.name.toString()
|
||||||
this.ownProperties = props.ownProperties
|
this.meta = props.meta
|
||||||
this.allProperties = props.allProperties
|
this.withDefault = props.withDefault
|
||||||
this.name = props.name + token
|
this.name = props.name + token
|
||||||
this.descriptor = props.descriptor
|
this.descriptor = props.descriptor
|
||||||
}
|
}
|
||||||
@ -217,74 +190,52 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val PropertyEditor: FunctionComponent<PropertyEditorProps> = functionalComponent("PropertyEditor") { props ->
|
public val PropertyEditor: FunctionComponent<PropertyEditorProps> = functionalComponent("PropertyEditor") { props ->
|
||||||
child(PropertyEditorItem) {
|
child(PropertyEditorItem) {
|
||||||
attrs {
|
attrs {
|
||||||
this.key = ""
|
this.key = ""
|
||||||
this.ownProperties = props.ownProperties
|
this.meta = props.meta
|
||||||
this.allProperties = props.allProperties
|
this.withDefault = props.withDefault
|
||||||
this.name = Name.EMPTY
|
this.name = Name.EMPTY
|
||||||
this.descriptor = props.descriptor
|
this.descriptor = props.descriptor
|
||||||
this.scope = props.scope
|
|
||||||
this.expanded = props.expanded
|
this.expanded = props.expanded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun RBuilder.propertyEditor(
|
public fun RBuilder.propertyEditor(
|
||||||
ownProperties: MutableMetaProvider,
|
ownProperties: ObservableMutableMeta,
|
||||||
allProperties: MetaProvider? = ownProperties,
|
allProperties: MetaProvider = ownProperties,
|
||||||
updateFlow: Flow<Name>? = null,
|
|
||||||
descriptor: MetaDescriptor? = null,
|
descriptor: MetaDescriptor? = null,
|
||||||
scope: CoroutineScope? = null,
|
|
||||||
key: Any? = null,
|
key: Any? = null,
|
||||||
expanded: Boolean? = null
|
expanded: Boolean? = null
|
||||||
) {
|
) {
|
||||||
child(PropertyEditor) {
|
child(PropertyEditor) {
|
||||||
attrs {
|
attrs {
|
||||||
this.ownProperties = ownProperties
|
this.meta = ownProperties
|
||||||
this.allProperties = allProperties
|
this.withDefault = allProperties
|
||||||
this.updateFlow = updateFlow
|
|
||||||
this.descriptor = descriptor
|
this.descriptor = descriptor
|
||||||
this.key = key?.toString() ?: ""
|
this.key = key?.toString() ?: ""
|
||||||
this.scope = scope
|
|
||||||
this.expanded = expanded
|
this.expanded = expanded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
private fun ObservableMutableMeta.flowUpdates(): Flow<Name> = callbackFlow {
|
|
||||||
onChange(this) { name ->
|
|
||||||
launch {
|
|
||||||
send(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
awaitClose {
|
|
||||||
removeListener(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public fun RBuilder.configEditor(
|
public fun RBuilder.configEditor(
|
||||||
config: ObservableMutableMeta,
|
config: ObservableMutableMeta,
|
||||||
default: MetaProvider? = null,
|
default: MetaProvider = config,
|
||||||
descriptor: MetaDescriptor? = null,
|
descriptor: MetaDescriptor? = null,
|
||||||
key: Any? = null,
|
key: Any? = null,
|
||||||
scope: CoroutineScope? = null,
|
): Unit = propertyEditor(config, default, descriptor, key = key)
|
||||||
): Unit = propertyEditor(config, default, config.flowUpdates(), descriptor, scope, key = key)
|
|
||||||
|
|
||||||
public fun Element.configEditor(
|
public fun Element.configEditor(
|
||||||
config: ObservableMutableMeta,
|
config: ObservableMutableMeta,
|
||||||
|
default: Meta = config,
|
||||||
descriptor: MetaDescriptor? = null,
|
descriptor: MetaDescriptor? = null,
|
||||||
default: Meta? = null,
|
|
||||||
key: Any? = null,
|
key: Any? = null,
|
||||||
scope: CoroutineScope? = null,
|
|
||||||
): Unit = render(this) {
|
): Unit = render(this) {
|
||||||
configEditor(config, default, descriptor, key, scope)
|
configEditor(config, default, descriptor, key = key)
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ import react.FunctionComponent
|
|||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.functionalComponent
|
import react.functionalComponent
|
||||||
import react.useState
|
import react.useState
|
||||||
|
import space.kscience.dataforge.meta.descriptors.ValueRequirement
|
||||||
import space.kscience.dataforge.meta.double
|
import space.kscience.dataforge.meta.double
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
@ -20,32 +21,34 @@ import styled.styledInput
|
|||||||
@JsExport
|
@JsExport
|
||||||
public val RangeValueChooser: FunctionComponent<ValueChooserProps> =
|
public val RangeValueChooser: FunctionComponent<ValueChooserProps> =
|
||||||
functionalComponent("RangeValueChooser") { props ->
|
functionalComponent("RangeValueChooser") { props ->
|
||||||
var innerValue by useState(props.item.double)
|
var innerValue by useState(props.actual.double)
|
||||||
var rangeDisabled: Boolean by useState(props.item == null)
|
var rangeDisabled: Boolean by useState(props.meta.value == null)
|
||||||
|
|
||||||
val handleDisable: (Event) -> Unit = {
|
val handleDisable: (Event) -> Unit = {
|
||||||
val checkBoxValue = (it.target as HTMLInputElement).checked
|
val checkBoxValue = (it.target as HTMLInputElement).checked
|
||||||
rangeDisabled = !checkBoxValue
|
rangeDisabled = !checkBoxValue
|
||||||
if(!checkBoxValue) {
|
props.meta.value = if(!checkBoxValue) {
|
||||||
props.valueChanged?.invoke(null)
|
null
|
||||||
} else {
|
} else {
|
||||||
props.valueChanged?.invoke(innerValue?.asValue())
|
innerValue?.asValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val handleChange: (Event) -> Unit = {
|
val handleChange: (Event) -> Unit = {
|
||||||
val newValue = (it.target as HTMLInputElement).value
|
val newValue = (it.target as HTMLInputElement).value
|
||||||
props.valueChanged?.invoke(newValue.toDoubleOrNull()?.asValue())
|
props.meta.value = newValue.toDoubleOrNull()?.asValue()
|
||||||
innerValue = newValue.toDoubleOrNull()
|
innerValue = newValue.toDoubleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
flexRow {
|
flexRow {
|
||||||
|
if(props.descriptor?.valueRequirement != ValueRequirement.REQUIRED) {
|
||||||
styledInput(type = InputType.checkBox) {
|
styledInput(type = InputType.checkBox) {
|
||||||
attrs {
|
attrs {
|
||||||
defaultChecked = rangeDisabled.not()
|
defaultChecked = rangeDisabled.not()
|
||||||
onChangeFunction = handleDisable
|
onChangeFunction = handleDisable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
styledInput(type = InputType.range) {
|
styledInput(type = InputType.range) {
|
||||||
css{
|
css{
|
||||||
@ -55,6 +58,7 @@ public val RangeValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
disabled = rangeDisabled
|
disabled = rangeDisabled
|
||||||
value = innerValue?.toString() ?: ""
|
value = innerValue?.toString() ?: ""
|
||||||
onChangeFunction = handleChange
|
onChangeFunction = handleChange
|
||||||
|
consumer.onTagEvent(this, "input", handleChange)
|
||||||
val minValue = props.descriptor?.attributes?.get("min").string
|
val minValue = props.descriptor?.attributes?.get("min").string
|
||||||
minValue?.let {
|
minValue?.let {
|
||||||
min = it
|
min = it
|
||||||
|
@ -13,14 +13,13 @@ import org.w3c.dom.events.Event
|
|||||||
import react.*
|
import react.*
|
||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.option
|
import react.dom.option
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.meta.boolean
|
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.descriptors.allowedValues
|
import space.kscience.dataforge.meta.descriptors.allowedValues
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.values.ValueType
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.values.asValue
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.values.int
|
||||||
import space.kscience.dataforge.values.*
|
import space.kscience.dataforge.values.string
|
||||||
import space.kscience.visionforge.Colors
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.widgetType
|
import space.kscience.visionforge.widgetType
|
||||||
import styled.css
|
import styled.css
|
||||||
@ -28,23 +27,19 @@ import styled.styledInput
|
|||||||
import styled.styledSelect
|
import styled.styledSelect
|
||||||
|
|
||||||
public external interface ValueChooserProps : RProps {
|
public external interface ValueChooserProps : RProps {
|
||||||
public var item: Meta?
|
|
||||||
public var descriptor: MetaDescriptor?
|
public var descriptor: MetaDescriptor?
|
||||||
|
public var meta: ObservableMutableMeta
|
||||||
//public var nullable: Boolean?
|
public var actual: Meta
|
||||||
public var valueChanged: ((Value?) -> Unit)?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val StringValueChooser: FunctionComponent<ValueChooserProps> =
|
public val StringValueChooser: FunctionComponent<ValueChooserProps> =
|
||||||
functionalComponent("StringValueChooser") { props ->
|
functionalComponent("StringValueChooser") { props ->
|
||||||
var value by useState(props.item.string ?: "")
|
var value by useState(props.actual.string ?: "")
|
||||||
val keyDown: (Event) -> Unit = { event ->
|
val keyDown: (Event) -> Unit = { event ->
|
||||||
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
||||||
value = (event.target as HTMLInputElement).value
|
value = (event.target as HTMLInputElement).value
|
||||||
if (value != props.item.string) {
|
props.meta.value = value.asValue()
|
||||||
props.valueChanged?.invoke(value.asValue())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val handleChange: (Event) -> Unit = {
|
val handleChange: (Event) -> Unit = {
|
||||||
@ -67,7 +62,7 @@ public val BooleanValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
functionalComponent("BooleanValueChooser") { props ->
|
functionalComponent("BooleanValueChooser") { props ->
|
||||||
val handleChange: (Event) -> Unit = {
|
val handleChange: (Event) -> Unit = {
|
||||||
val newValue = (it.target as HTMLInputElement).checked
|
val newValue = (it.target as HTMLInputElement).checked
|
||||||
props.valueChanged?.invoke(newValue.asValue())
|
props.meta.value = newValue.asValue()
|
||||||
}
|
}
|
||||||
styledInput(type = InputType.checkBox) {
|
styledInput(type = InputType.checkBox) {
|
||||||
css {
|
css {
|
||||||
@ -75,7 +70,7 @@ public val BooleanValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
}
|
}
|
||||||
attrs {
|
attrs {
|
||||||
//this.attributes["indeterminate"] = (props.item == null).toString()
|
//this.attributes["indeterminate"] = (props.item == null).toString()
|
||||||
defaultChecked = props.item.boolean ?: false
|
defaultChecked = props.actual.boolean ?: false
|
||||||
onChangeFunction = handleChange
|
onChangeFunction = handleChange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +79,7 @@ public val BooleanValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
@JsExport
|
@JsExport
|
||||||
public val NumberValueChooser: FunctionComponent<ValueChooserProps> =
|
public val NumberValueChooser: FunctionComponent<ValueChooserProps> =
|
||||||
functionalComponent("NumberValueChooser") { props ->
|
functionalComponent("NumberValueChooser") { props ->
|
||||||
var innerValue by useState(props.item.string ?: "")
|
var innerValue by useState(props.actual.string ?: "")
|
||||||
val keyDown: (Event) -> Unit = { event ->
|
val keyDown: (Event) -> Unit = { event ->
|
||||||
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
||||||
innerValue = (event.target as HTMLInputElement).value
|
innerValue = (event.target as HTMLInputElement).value
|
||||||
@ -92,7 +87,7 @@ public val NumberValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
if (number == null) {
|
if (number == null) {
|
||||||
console.error("The input value $innerValue is not a number")
|
console.error("The input value $innerValue is not a number")
|
||||||
} else {
|
} else {
|
||||||
props.valueChanged?.invoke(number.asValue())
|
props.meta.value = number.asValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,10 +118,10 @@ public val NumberValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
@JsExport
|
@JsExport
|
||||||
public val ComboValueChooser: FunctionComponent<ValueChooserProps> =
|
public val ComboValueChooser: FunctionComponent<ValueChooserProps> =
|
||||||
functionalComponent("ComboValueChooser") { props ->
|
functionalComponent("ComboValueChooser") { props ->
|
||||||
var selected by useState(props.item.string ?: "")
|
var selected by useState(props.actual.string ?: "")
|
||||||
val handleChange: (Event) -> Unit = {
|
val handleChange: (Event) -> Unit = {
|
||||||
selected = (it.target as HTMLSelectElement).value
|
selected = (it.target as HTMLSelectElement).value
|
||||||
props.valueChanged?.invoke(selected.asValue())
|
props.meta.value = selected.asValue()
|
||||||
}
|
}
|
||||||
styledSelect {
|
styledSelect {
|
||||||
css {
|
css {
|
||||||
@ -138,7 +133,7 @@ public val ComboValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
attrs {
|
attrs {
|
||||||
this.value = props.item?.string ?: ""
|
this.value = props.actual.string ?: ""
|
||||||
multiple = false
|
multiple = false
|
||||||
onChangeFunction = handleChange
|
onChangeFunction = handleChange
|
||||||
}
|
}
|
||||||
@ -149,14 +144,14 @@ public val ComboValueChooser: FunctionComponent<ValueChooserProps> =
|
|||||||
public val ColorValueChooser: FunctionComponent<ValueChooserProps> =
|
public val ColorValueChooser: FunctionComponent<ValueChooserProps> =
|
||||||
functionalComponent("ColorValueChooser") { props ->
|
functionalComponent("ColorValueChooser") { props ->
|
||||||
var value by useState(
|
var value by useState(
|
||||||
props.item?.value?.let { value ->
|
props.actual.value?.let { value ->
|
||||||
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
|
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
|
||||||
else value.string
|
else value.string
|
||||||
} ?: "#000000"
|
} ?: "#000000"
|
||||||
)
|
)
|
||||||
val handleChange: (Event) -> Unit = {
|
val handleChange: (Event) -> Unit = {
|
||||||
value = (it.target as HTMLInputElement).value
|
value = (it.target as HTMLInputElement).value
|
||||||
props.valueChanged?.invoke(value.asValue())
|
props.meta.value = value.asValue()
|
||||||
}
|
}
|
||||||
styledInput(type = InputType.color) {
|
styledInput(type = InputType.color) {
|
||||||
css {
|
css {
|
||||||
@ -189,19 +184,3 @@ public val ValueChooser: FunctionComponent<ValueChooserProps> = functionalCompon
|
|||||||
else -> child(StringValueChooser, props)
|
else -> child(StringValueChooser, props)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RBuilder.valueChooser(
|
|
||||||
name: Name,
|
|
||||||
item: Meta?,
|
|
||||||
descriptor: MetaDescriptor? = null,
|
|
||||||
callback: (Value?) -> Unit,
|
|
||||||
) {
|
|
||||||
child(ValueChooser) {
|
|
||||||
attrs {
|
|
||||||
key = name.toString()
|
|
||||||
this.item = item
|
|
||||||
this.descriptor = descriptor
|
|
||||||
this.valueChanged = callback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -15,7 +15,6 @@ import space.kscience.dataforge.names.isEmpty
|
|||||||
import space.kscience.dataforge.names.length
|
import space.kscience.dataforge.names.length
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
import space.kscience.visionforge.computeProperties
|
import space.kscience.visionforge.computeProperties
|
||||||
import space.kscience.visionforge.propertyChanges
|
|
||||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
import space.kscience.visionforge.react.ThreeCanvasComponent
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.react.flexColumn
|
||||||
import space.kscience.visionforge.react.flexRow
|
import space.kscience.visionforge.react.flexRow
|
||||||
@ -137,7 +136,6 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
|||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = vision.meta,
|
ownProperties = vision.meta,
|
||||||
allProperties = vision.computeProperties(),
|
allProperties = vision.computeProperties(),
|
||||||
updateFlow = vision.propertyChanges,
|
|
||||||
descriptor = vision.descriptor,
|
descriptor = vision.descriptor,
|
||||||
key = selected
|
key = selected
|
||||||
)
|
)
|
||||||
|
@ -8,11 +8,14 @@ import ringui.Island
|
|||||||
import ringui.SmartTabs
|
import ringui.SmartTabs
|
||||||
import ringui.Tab
|
import ringui.Tab
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.Vision
|
||||||
|
import space.kscience.visionforge.computeProperties
|
||||||
|
import space.kscience.visionforge.getStyle
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.react.flexColumn
|
||||||
import space.kscience.visionforge.react.metaViewer
|
import space.kscience.visionforge.react.metaViewer
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
import space.kscience.visionforge.react.propertyEditor
|
||||||
import space.kscience.visionforge.solid.SolidReference
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
|
import space.kscience.visionforge.styles
|
||||||
|
|
||||||
public fun RBuilder.ringPropertyEditor(
|
public fun RBuilder.ringPropertyEditor(
|
||||||
vision: Vision,
|
vision: Vision,
|
||||||
@ -30,7 +33,6 @@ public fun RBuilder.ringPropertyEditor(
|
|||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = vision.meta,
|
ownProperties = vision.meta,
|
||||||
allProperties = vision.computeProperties(),
|
allProperties = vision.computeProperties(),
|
||||||
updateFlow = vision.propertyChanges,
|
|
||||||
descriptor = descriptor,
|
descriptor = descriptor,
|
||||||
key = key
|
key = key
|
||||||
)
|
)
|
||||||
|
@ -72,7 +72,7 @@ internal val CanvasControls: FunctionComponent<CanvasControlsProps> = functional
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = props.options,
|
ownProperties = props.options.meta,
|
||||||
allProperties = props.options.meta.withDefault(Canvas3DOptions.descriptor.defaultNode),
|
allProperties = props.options.meta.withDefault(Canvas3DOptions.descriptor.defaultNode),
|
||||||
descriptor = Canvas3DOptions.descriptor,
|
descriptor = Canvas3DOptions.descriptor,
|
||||||
expanded = false
|
expanded = false
|
||||||
|
@ -12,10 +12,12 @@ import space.kscience.dataforge.misc.DFExperimental
|
|||||||
import space.kscience.dataforge.misc.Type
|
import space.kscience.dataforge.misc.Type
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.dataforge.values.Value
|
import space.kscience.dataforge.values.Value
|
||||||
import space.kscience.dataforge.values.asValue
|
import space.kscience.dataforge.values.asValue
|
||||||
import space.kscience.dataforge.values.boolean
|
import space.kscience.dataforge.values.boolean
|
||||||
import space.kscience.visionforge.Vision.Companion.TYPE
|
import space.kscience.visionforge.Vision.Companion.TYPE
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A root type for display hierarchy
|
* A root type for display hierarchy
|
||||||
@ -129,3 +131,17 @@ public var Vision.visible: Boolean?
|
|||||||
get() = getPropertyValue(Vision.VISIBLE_KEY)?.boolean
|
get() = getPropertyValue(Vision.VISIBLE_KEY)?.boolean
|
||||||
set(value) = meta.setValue(Vision.VISIBLE_KEY, value?.asValue())
|
set(value) = meta.setValue(Vision.VISIBLE_KEY, value?.asValue())
|
||||||
|
|
||||||
|
|
||||||
|
public fun <V : Vision, T> V.useProperty(
|
||||||
|
property: KProperty1<V, T>,
|
||||||
|
owner: Any? = null,
|
||||||
|
callBack: V.(T) -> Unit,
|
||||||
|
) {
|
||||||
|
//Pass initial value.
|
||||||
|
callBack(property.get(this))
|
||||||
|
meta.onChange(owner) { name ->
|
||||||
|
if (name.startsWith(property.name.asName())) {
|
||||||
|
callBack(property.get(this@useProperty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -44,7 +44,7 @@ public open class VisionBase(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private val listeners = HashSet<MetaListener>()
|
private val listeners: MutableList<MetaListener> = mutableListOf()
|
||||||
|
|
||||||
private inner class VisionProperties(val pathName: Name) : ObservableMutableMeta {
|
private inner class VisionProperties(val pathName: Name) : ObservableMutableMeta {
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionBase
|
import space.kscience.visionforge.VisionBase
|
||||||
import space.kscience.visionforge.setProperty
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("vision.markup")
|
@SerialName("vision.markup")
|
||||||
@ -20,15 +19,11 @@ public class VisionOfMarkup(
|
|||||||
) : VisionBase() {
|
) : VisionBase() {
|
||||||
|
|
||||||
//FIXME to be removed after https://github.com/Kotlin/kotlinx.serialization/issues/1602 fix
|
//FIXME to be removed after https://github.com/Kotlin/kotlinx.serialization/issues/1602 fix
|
||||||
override var properties: MutableMeta? = null
|
protected override var properties: MutableMeta? = null
|
||||||
|
|
||||||
//TODO add templates
|
//TODO add templates
|
||||||
|
|
||||||
public var content: String?
|
public var content: String? by meta.string(CONTENT_PROPERTY_KEY)
|
||||||
get() = meta.getMeta(CONTENT_PROPERTY_KEY).string
|
|
||||||
set(value) {
|
|
||||||
setProperty(CONTENT_PROPERTY_KEY, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public val CONTENT_PROPERTY_KEY: Name = "content".asName()
|
public val CONTENT_PROPERTY_KEY: Name = "content".asName()
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
package space.kscience.visionforge.markup
|
package space.kscience.visionforge.markup
|
||||||
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.dom.clear
|
||||||
|
import kotlinx.html.dom.append
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
|
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
|
||||||
|
import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.PluginFactory
|
import space.kscience.dataforge.context.PluginFactory
|
||||||
import space.kscience.dataforge.context.PluginTag
|
import space.kscience.dataforge.context.PluginTag
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.visionforge.ElementVisionRenderer
|
import space.kscience.visionforge.*
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.markup.VisionOfMarkup.Companion.COMMONMARK_FORMAT
|
||||||
import space.kscience.visionforge.VisionClient
|
import space.kscience.visionforge.markup.VisionOfMarkup.Companion.GFM_FORMAT
|
||||||
import space.kscience.visionforge.VisionPlugin
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class MarkupPlugin : VisionPlugin(), ElementVisionRenderer {
|
public class MarkupPlugin : VisionPlugin(), ElementVisionRenderer {
|
||||||
@ -26,8 +29,20 @@ public class MarkupPlugin : VisionPlugin(), ElementVisionRenderer {
|
|||||||
override fun render(element: Element, vision: Vision, meta: Meta) {
|
override fun render(element: Element, vision: Vision, meta: Meta) {
|
||||||
require(vision is VisionOfMarkup) { "The vision is not a markup vision" }
|
require(vision is VisionOfMarkup) { "The vision is not a markup vision" }
|
||||||
val div = document.createElement("div")
|
val div = document.createElement("div")
|
||||||
|
val flavour = when (vision.format) {
|
||||||
|
COMMONMARK_FORMAT -> CommonMarkFlavourDescriptor()
|
||||||
|
GFM_FORMAT -> GFMFlavourDescriptor()
|
||||||
|
//TODO add new formats via plugins
|
||||||
|
else-> error("Format ${vision.format} not recognized")
|
||||||
|
}
|
||||||
|
vision.useProperty(VisionOfMarkup::content) {
|
||||||
|
div.clear()
|
||||||
|
div.append {
|
||||||
|
markdown(flavour) { vision.content ?: "" }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
element.append(div)
|
element.append(div)
|
||||||
TODO()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object : PluginFactory<MarkupPlugin> {
|
public companion object : PluginFactory<MarkupPlugin> {
|
||||||
|
@ -5,7 +5,6 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
|||||||
import space.kscience.dataforge.meta.descriptors.scheme
|
import space.kscience.dataforge.meta.descriptors.scheme
|
||||||
import space.kscience.dataforge.meta.descriptors.value
|
import space.kscience.dataforge.meta.descriptors.value
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.values.ValueType
|
|
||||||
import space.kscience.visionforge.hide
|
import space.kscience.visionforge.hide
|
||||||
import space.kscience.visionforge.widgetType
|
import space.kscience.visionforge.widgetType
|
||||||
|
|
||||||
@ -21,20 +20,21 @@ public class Clipping : Scheme() {
|
|||||||
attributes["min"] = 0.0
|
attributes["min"] = 0.0
|
||||||
attributes["max"] = 1.0
|
attributes["max"] = 1.0
|
||||||
attributes["step"] = 0.01
|
attributes["step"] = 0.01
|
||||||
|
default(1.0)
|
||||||
}
|
}
|
||||||
value(Clipping::y) {
|
value(Clipping::y) {
|
||||||
widgetType = "range"
|
widgetType = "range"
|
||||||
attributes["min"] = 0.0
|
attributes["min"] = 0.0
|
||||||
attributes["max"] = 1.0
|
attributes["max"] = 1.0
|
||||||
attributes["step"] = 0.01
|
attributes["step"] = 0.01
|
||||||
|
default(1.0)
|
||||||
}
|
}
|
||||||
value(Clipping::z) {
|
value(Clipping::z) {
|
||||||
widgetType = "range"
|
widgetType = "range"
|
||||||
attributes["min"] = 0.0
|
attributes["min"] = 0.0
|
||||||
attributes["max"] = 1.0
|
attributes["max"] = 1.0
|
||||||
attributes["step"] = 0.01
|
attributes["step"] = 0.01
|
||||||
|
default(1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,16 +168,13 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Clipping planes
|
//Clipping planes
|
||||||
options.meta.onChange(this@ThreeCanvas) { name->
|
options.useProperty(Canvas3DOptions::clipping){clipping ->
|
||||||
if (name.startsWith(Canvas3DOptions::clipping.name.asName())) {
|
|
||||||
val clipping = options.clipping
|
|
||||||
if (!clipping.meta.isEmpty()) {
|
if (!clipping.meta.isEmpty()) {
|
||||||
renderer.localClippingEnabled = true
|
renderer.localClippingEnabled = true
|
||||||
boundingBox?.let { boundingBox ->
|
boundingBox?.let { boundingBox ->
|
||||||
val xClippingPlane = clipping.x?.let {
|
val xClippingPlane = clipping.x?.let {
|
||||||
val absoluteValue = boundingBox.min.x + (boundingBox.max.x - boundingBox.min.x) * it
|
val absoluteValue = boundingBox.min.x + (boundingBox.max.x - boundingBox.min.x) * it
|
||||||
Plane(Vector3(-1.0, 0.0, 0.0), absoluteValue)
|
Plane(Vector3(-1.0, 0.0, 0.0), absoluteValue)
|
||||||
|
|
||||||
}
|
}
|
||||||
val yClippingPlane = clipping.y?.let {
|
val yClippingPlane = clipping.y?.let {
|
||||||
val absoluteValue = boundingBox.min.y + (boundingBox.max.y - boundingBox.min.y) * it
|
val absoluteValue = boundingBox.min.y + (boundingBox.max.y - boundingBox.min.y) * it
|
||||||
@ -194,7 +191,9 @@ public class ThreeCanvas(
|
|||||||
} else {
|
} else {
|
||||||
renderer.localClippingEnabled = false
|
renderer.localClippingEnabled = false
|
||||||
}
|
}
|
||||||
} else if (name.startsWith(Canvas3DOptions::size.name.asName())) {
|
}
|
||||||
|
|
||||||
|
options.useProperty(Canvas3DOptions::size){
|
||||||
canvas.style.apply {
|
canvas.style.apply {
|
||||||
minWidth = "${options.size.minWith.toInt()}px"
|
minWidth = "${options.size.minWith.toInt()}px"
|
||||||
maxWidth = "${options.size.maxWith.toInt()}px"
|
maxWidth = "${options.size.maxWith.toInt()}px"
|
||||||
@ -204,7 +203,6 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve full name of the object relative to the global root
|
* Resolve full name of the object relative to the global root
|
||||||
|
Loading…
Reference in New Issue
Block a user