0.2.0 #71

Merged
altavir merged 139 commits from dev into master 2022-01-24 09:44:18 +03:00
12 changed files with 223 additions and 230 deletions
Showing only changes of commit b5fdc6c4fe - Show all commits

View File

@ -5,7 +5,7 @@ plugins {
group = "ru.mipt.npm" group = "ru.mipt.npm"
val ktorVersion: String = ru.mipt.npm.gradle.KScienceVersions.ktorVersion val ktorVersion: String = npmlibs.versions.ktor.get()
kscience { kscience {
useCoroutines() useCoroutines()
@ -45,17 +45,17 @@ kotlin {
jvmMain { jvmMain {
dependencies { dependencies {
implementation("org.apache.commons:commons-math3:3.6.1") implementation("org.apache.commons:commons-math3:3.6.1")
implementation("io.ktor:ktor-server-cio:$ktorVersion") implementation(npmlibs.ktor.server.cio)
implementation("io.ktor:ktor-serialization:$ktorVersion") implementation(npmlibs.ktor.serialization)
} }
} }
jsMain { jsMain {
dependencies { dependencies {
implementation(project(":ui:ring")) implementation(project(":ui:ring"))
implementation("io.ktor:ktor-client-js:$ktorVersion") implementation(npmlibs.ktor.client.js)
implementation("io.ktor:ktor-client-serialization:$ktorVersion") implementation(npmlibs.ktor.client.serialization)
implementation(project(":visionforge-threejs")) implementation(project(":visionforge-threejs"))
implementation(devNpm("webpack-bundle-analyzer", "4.4.0")) //implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
} }
} }
} }

View File

@ -8,3 +8,5 @@ org.gradle.parallel=true
publishing.github=false publishing.github=false
publishing.sonatype=false publishing.sonatype=false
toolsVersion=0.10.9-kotlin-1.6.10

View File

@ -1,6 +1,6 @@
pluginManagement { pluginManagement {
val toolsVersion = "0.10.7" val toolsVersion: String by extra
repositories { repositories {
//mavenLocal() //mavenLocal()
@ -23,6 +23,9 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
enableFeaturePreview("VERSION_CATALOGS") enableFeaturePreview("VERSION_CATALOGS")
dependencyResolutionManagement { dependencyResolutionManagement {
val toolsVersion: String by extra
repositories { repositories {
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
mavenCentral() mavenCentral()
@ -30,7 +33,7 @@ dependencyResolutionManagement {
versionCatalogs { versionCatalogs {
create("npmlibs") { create("npmlibs") {
from("ru.mipt.npm:version-catalog:0.10.7") from("ru.mipt.npm:version-catalog:$toolsVersion")
} }
} }
} }

View File

@ -5,35 +5,34 @@ import org.w3c.dom.HTMLOptionElement
import org.w3c.dom.HTMLSelectElement import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.asList import org.w3c.dom.asList
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import react.FunctionComponent import react.FC
import react.dom.attrs import react.dom.attrs
import react.dom.option import react.dom.option
import react.dom.select import react.dom.select
import react.functionComponent import react.fc
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
@JsExport @JsExport
public val MultiSelectChooser: FunctionComponent<ValueChooserProps> = public val MultiSelectChooser: FC<ValueChooserProps> = fc("MultiSelectChooser") { props ->
functionComponent("MultiSelectChooser") { props -> 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.meta.value = newSelected.asValue()
props.meta.value = newSelected.asValue()
}
select {
attrs {
multiple = true
values = (props.actual.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
onChangeFunction = onChange
}
props.descriptor?.allowedValues?.forEach { optionValue ->
option {
+optionValue.string
}
}
}
} }
select {
attrs {
multiple = true
values = (props.actual.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
onChangeFunction = onChange
}
props.descriptor?.allowedValues?.forEach { optionValue ->
option {
+optionValue.string
}
}
}
}

View File

@ -47,10 +47,9 @@ public external interface PropertyEditorProps : Props {
public var expanded: Boolean? public var expanded: Boolean?
} }
private val PropertyEditorItem: FunctionComponent<PropertyEditorProps> = private val PropertyEditorItem: FC<PropertyEditorProps> = fc("PropertyEditorItem") { props ->
functionComponent("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 }
@ -129,7 +128,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
width = 160.px width = 160.px
margin(1.px, 5.px) margin(1.px, 5.px)
} }
ValueChooser{ ValueChooser {
attrs { attrs {
this.descriptor = descriptor this.descriptor = descriptor
this.meta = ownProperty this.meta = ownProperty
@ -193,7 +192,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
} }
@JsExport @JsExport
public val PropertyEditor: FunctionComponent<PropertyEditorProps> = functionComponent("PropertyEditor") { props -> public val PropertyEditor: FC<PropertyEditorProps> = fc("PropertyEditor") { props ->
child(PropertyEditorItem) { child(PropertyEditorItem) {
attrs { attrs {
this.key = "" this.key = ""
@ -211,7 +210,7 @@ public fun RBuilder.propertyEditor(
allProperties: MetaProvider = ownProperties, allProperties: MetaProvider = ownProperties,
descriptor: MetaDescriptor? = null, descriptor: MetaDescriptor? = null,
key: Any? = null, key: Any? = null,
expanded: Boolean? = null expanded: Boolean? = null,
) { ) {
child(PropertyEditor) { child(PropertyEditor) {
attrs { attrs {

View File

@ -6,9 +6,9 @@ import kotlinx.html.InputType
import kotlinx.html.js.onChangeFunction import kotlinx.html.js.onChangeFunction
import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import react.FunctionComponent import react.FC
import react.dom.attrs import react.dom.attrs
import react.functionComponent import react.fc
import react.useState import react.useState
import space.kscience.dataforge.meta.descriptors.ValueRequirement import space.kscience.dataforge.meta.descriptors.ValueRequirement
import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.double
@ -19,58 +19,57 @@ import styled.css
import styled.styledInput import styled.styledInput
@JsExport @JsExport
public val RangeValueChooser: FunctionComponent<ValueChooserProps> = public val RangeValueChooser: FC<ValueChooserProps> = fc("RangeValueChooser") { props ->
functionComponent("RangeValueChooser") { props -> var innerValue by useState(props.actual.double)
var innerValue by useState(props.actual.double) var rangeDisabled: Boolean by useState(props.meta.value == 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
props.meta.value = if(!checkBoxValue) { props.meta.value = if (!checkBoxValue) {
null null
} else { } else {
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.meta.value = newValue.toDoubleOrNull()?.asValue() props.meta.value = newValue.toDoubleOrNull()?.asValue()
innerValue = newValue.toDoubleOrNull() innerValue = newValue.toDoubleOrNull()
} }
flexRow { flexRow {
if(props.descriptor?.valueRequirement != ValueRequirement.REQUIRED) { if (props.descriptor?.valueRequirement != ValueRequirement.REQUIRED) {
styledInput(type = InputType.checkBox) { styledInput(type = InputType.checkBox) {
attrs {
defaultChecked = rangeDisabled.not()
onChangeFunction = handleDisable
}
}
}
styledInput(type = InputType.range) {
css{
width = 100.pct
}
attrs { attrs {
disabled = rangeDisabled defaultChecked = rangeDisabled.not()
value = innerValue?.toString() ?: "" onChangeFunction = handleDisable
onChangeFunction = handleChange }
consumer.onTagEvent(this, "input", handleChange) }
val minValue = props.descriptor?.attributes?.get("min").string }
minValue?.let {
min = it styledInput(type = InputType.range) {
} css {
val maxValue = props.descriptor?.attributes?.get("max").string width = 100.pct
maxValue?.let { }
max = it attrs {
} disabled = rangeDisabled
props.descriptor?.attributes?.get("step").string?.let { value = innerValue?.toString() ?: ""
step = it onChangeFunction = handleChange
} consumer.onTagEvent(this, "input", handleChange)
val minValue = props.descriptor?.attributes?.get("min").string
minValue?.let {
min = it
}
val maxValue = props.descriptor?.attributes?.get("max").string
maxValue?.let {
max = it
}
props.descriptor?.attributes?.get("step").string?.let {
step = it
} }
} }
} }
} }
}

View File

@ -21,13 +21,11 @@ public external interface ThreeCanvasProps : Props {
public var selected: Name? public var selected: Name?
} }
public val ThreeCanvasComponent: FunctionComponent<ThreeCanvasProps> = functionComponent( public val ThreeCanvasComponent: FC<ThreeCanvasProps> = fc("ThreeCanvasComponent") { props ->
"ThreeCanvasComponent"
) { props ->
val elementRef = useRef<Element>(null) val elementRef = useRef<Element>(null)
var canvas by useState<ThreeCanvas?>(null) var canvas by useState<ThreeCanvas?>(null)
val three: ThreePlugin = useMemo(props.context){ props.context.fetch(ThreePlugin) } val three: ThreePlugin = useMemo(props.context) { props.context.fetch(ThreePlugin) }
useEffect(props.solid, props.options, elementRef) { useEffect(props.solid, props.options, elementRef) {
if (canvas == null) { if (canvas == null) {

View File

@ -28,7 +28,7 @@ public external interface ObjectTreeProps : Props {
public var clickCallback: (Name) -> Unit public var clickCallback: (Name) -> Unit
} }
private val TreeLabel = functionComponent<ObjectTreeProps> { props -> private val TreeLabel = fc<ObjectTreeProps> { props ->
val token = useMemo(props.name) { props.name.lastOrNull()?.toString() ?: "World" } val token = useMemo(props.name) { props.name.lastOrNull()?.toString() ?: "World" }
styledSpan { styledSpan {
css { css {
@ -107,14 +107,14 @@ private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
} }
@JsExport @JsExport
public val ObjectTree: FunctionComponent<ObjectTreeProps> = functionComponent("ObjectTree") { props -> public val ObjectTree: FC<ObjectTreeProps> = fc("ObjectTree") { props ->
visionTree(props) visionTree(props)
} }
public fun RBuilder.visionTree( public fun RBuilder.visionTree(
vision: Vision, vision: Vision,
selected: Name? = null, selected: Name? = null,
clickCallback: (Name) -> Unit = {} clickCallback: (Name) -> Unit = {},
) { ) {
child(ObjectTree) { child(ObjectTree) {
attrs { attrs {

View File

@ -10,11 +10,11 @@ import kotlinx.html.js.onKeyDownFunction
import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLSelectElement import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import react.FunctionComponent import react.FC
import react.Props import react.Props
import react.dom.attrs import react.dom.attrs
import react.dom.option import react.dom.option
import react.functionComponent import react.fc
import react.useState import react.useState
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
@ -36,136 +36,131 @@ public external interface ValueChooserProps : Props {
} }
@JsExport @JsExport
public val StringValueChooser: FunctionComponent<ValueChooserProps> = public val StringValueChooser: FC<ValueChooserProps> = fc("StringValueChooser") { props ->
functionComponent("StringValueChooser") { props -> var value by useState(props.actual.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 props.meta.value = value.asValue()
props.meta.value = value.asValue()
}
} }
val handleChange: (Event) -> Unit = { }
value = (it.target as HTMLInputElement).value val handleChange: (Event) -> Unit = {
value = (it.target as HTMLInputElement).value
}
styledInput(type = InputType.text) {
css {
width = 100.pct
} }
styledInput(type = InputType.text) { attrs {
css { this.value = value
width = 100.pct onKeyDownFunction = keyDown
} onChangeFunction = handleChange
attrs { }
this.value = value }
onKeyDownFunction = keyDown }
onChangeFunction = handleChange
@JsExport
public val BooleanValueChooser: FC<ValueChooserProps> = fc("BooleanValueChooser") { props ->
val handleChange: (Event) -> Unit = {
val newValue = (it.target as HTMLInputElement).checked
props.meta.value = newValue.asValue()
}
styledInput(type = InputType.checkBox) {
css {
width = 100.pct
}
attrs {
//this.attributes["indeterminate"] = (props.item == null).toString()
checked = props.actual.boolean ?: false
onChangeFunction = handleChange
}
}
}
@JsExport
public val NumberValueChooser: FC<ValueChooserProps> = fc("NumberValueChooser") { props ->
var innerValue by useState(props.actual.string ?: "")
val keyDown: (Event) -> Unit = { event ->
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
innerValue = (event.target as HTMLInputElement).value
val number = innerValue.toDoubleOrNull()
if (number == null) {
console.error("The input value $innerValue is not a number")
} else {
props.meta.value = number.asValue()
} }
} }
} }
val handleChange: (Event) -> Unit = {
@JsExport innerValue = (it.target as HTMLInputElement).value
public val BooleanValueChooser: FunctionComponent<ValueChooserProps> = }
functionComponent("BooleanValueChooser") { props -> styledInput(type = InputType.number) {
val handleChange: (Event) -> Unit = { css {
val newValue = (it.target as HTMLInputElement).checked width = 100.pct
props.meta.value = newValue.asValue()
} }
styledInput(type = InputType.checkBox) { attrs {
css { value = innerValue
width = 100.pct onKeyDownFunction = keyDown
onChangeFunction = handleChange
props.descriptor?.attributes?.get("step").string?.let {
step = it
} }
attrs { props.descriptor?.attributes?.get("min").string?.let {
//this.attributes["indeterminate"] = (props.item == null).toString() min = it
checked = props.actual.boolean ?: false }
onChangeFunction = handleChange props.descriptor?.attributes?.get("max").string?.let {
max = it
} }
} }
} }
}
@JsExport @JsExport
public val NumberValueChooser: FunctionComponent<ValueChooserProps> = public val ComboValueChooser: FC<ValueChooserProps> = fc("ComboValueChooser") { props ->
functionComponent("NumberValueChooser") { props -> var selected by useState(props.actual.string ?: "")
var innerValue by useState(props.actual.string ?: "") val handleChange: (Event) -> Unit = {
val keyDown: (Event) -> Unit = { event -> selected = (it.target as HTMLSelectElement).value
if (event.type == "keydown" && event.asDynamic().key == "Enter") { props.meta.value = selected.asValue()
innerValue = (event.target as HTMLInputElement).value }
val number = innerValue.toDoubleOrNull() styledSelect {
if (number == null) { css {
console.error("The input value $innerValue is not a number") width = 100.pct
} else { }
props.meta.value = number.asValue() props.descriptor?.allowedValues?.forEach {
} option {
+it.string
} }
} }
val handleChange: (Event) -> Unit = { attrs {
innerValue = (it.target as HTMLInputElement).value this.value = props.actual.string ?: ""
} multiple = false
styledInput(type = InputType.number) { onChangeFunction = handleChange
css {
width = 100.pct
}
attrs {
value = innerValue
onKeyDownFunction = keyDown
onChangeFunction = handleChange
props.descriptor?.attributes?.get("step").string?.let {
step = it
}
props.descriptor?.attributes?.get("min").string?.let {
min = it
}
props.descriptor?.attributes?.get("max").string?.let {
max = it
}
}
} }
} }
}
@JsExport @JsExport
public val ComboValueChooser: FunctionComponent<ValueChooserProps> = public val ColorValueChooser: FC<ValueChooserProps> = fc("ColorValueChooser") { props ->
functionComponent("ComboValueChooser") { props -> val handleChange: (Event) -> Unit = {
var selected by useState(props.actual.string ?: "") props.meta.value = (it.target as HTMLInputElement).value.asValue()
val handleChange: (Event) -> Unit = { }
selected = (it.target as HTMLSelectElement).value styledInput(type = InputType.color) {
props.meta.value = selected.asValue() css {
width = 100.pct
margin(0.px)
} }
styledSelect { attrs {
css { this.value = props.actual.value?.let { value ->
width = 100.pct if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
} else value.string
props.descriptor?.allowedValues?.forEach { } ?: "#000000"
option { onChangeFunction = handleChange
+it.string
}
}
attrs {
this.value = props.actual.string ?: ""
multiple = false
onChangeFunction = handleChange
}
} }
} }
}
@JsExport @JsExport
public val ColorValueChooser: FunctionComponent<ValueChooserProps> = public val ValueChooser: FC<ValueChooserProps> = fc("ValueChooser") { props ->
functionComponent("ColorValueChooser") { props ->
val handleChange: (Event) -> Unit = {
props.meta.value = (it.target as HTMLInputElement).value.asValue()
}
styledInput(type = InputType.color) {
css {
width = 100.pct
margin(0.px)
}
attrs {
this.value = props.actual.value?.let { value ->
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
else value.string
} ?: "#000000"
onChangeFunction = handleChange
}
}
}
@JsExport
public val ValueChooser: FunctionComponent<ValueChooserProps> = functionComponent("ValueChooser") { props ->
val rawInput by useState(false) val rawInput by useState(false)
val descriptor = props.descriptor val descriptor = props.descriptor

View File

@ -5,7 +5,9 @@ plugins {
val dataforgeVersion: String by rootProject.extra val dataforgeVersion: String by rootProject.extra
kscience{ kscience{
useSerialization() useSerialization{
json()
}
} }
kotlin { kotlin {

View File

@ -71,35 +71,31 @@ public interface ValueChooser {
public companion object { public companion object {
private fun findWidgetByType(context: Context, type: String): Factory? { private fun findWidgetByType(context: Context, type: String): Factory? = when (Name.parse(type)) {
return when (Name.parse(type)) { TextValueChooser.name -> TextValueChooser
TextValueChooser.name -> TextValueChooser ColorValueChooser.name -> ColorValueChooser
ColorValueChooser.name -> ColorValueChooser ComboBoxValueChooser.name -> ComboBoxValueChooser
ComboBoxValueChooser.name -> ComboBoxValueChooser else -> null//context.provideByType(type)//Search for additional factories in the plugin
else -> null//context.provideByType(type)//Search for additional factories in the plugin
}
} }
private fun build(context: Context, descriptor: MetaDescriptor?): ValueChooser { private fun build(context: Context, descriptor: MetaDescriptor?): ValueChooser = if (descriptor == null) {
return if (descriptor == null) { TextValueChooser();
TextValueChooser(); } else {
} else { val widgetType = descriptor.widgetType
val widgetType = descriptor.widgetType val chooser: ValueChooser = when {
val chooser: ValueChooser = when { widgetType != null -> {
widgetType != null -> { findWidgetByType(
findWidgetByType( context,
context, widgetType
widgetType )?.invoke(
)?.invoke( descriptor.widget
descriptor.widget ) ?: TextValueChooser()
) ?: TextValueChooser()
}
!descriptor.allowedValues.isNullOrEmpty() -> ComboBoxValueChooser()
else -> TextValueChooser()
} }
chooser.descriptor = descriptor !descriptor.allowedValues.isNullOrEmpty() -> ComboBoxValueChooser()
chooser else -> TextValueChooser()
} }
chooser.descriptor = descriptor
chooser
} }
public fun build( public fun build(

View File

@ -42,6 +42,7 @@ public interface Point3D {
} }
} }
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(Point3DSerializer::class) @Serializable(Point3DSerializer::class)
public interface MutablePoint3D : Point3D { public interface MutablePoint3D : Point3D {
override var x: Float override var x: Float
@ -56,7 +57,6 @@ internal object Point3DSerializer : KSerializer<Point3D> {
override val descriptor: SerialDescriptor = Point3DImpl.serializer().descriptor override val descriptor: SerialDescriptor = Point3DImpl.serializer().descriptor
override fun deserialize(decoder: Decoder): MutablePoint3D = decoder.decodeSerializableValue(Point3DImpl.serializer()) override fun deserialize(decoder: Decoder): MutablePoint3D = decoder.decodeSerializableValue(Point3DImpl.serializer())
override fun serialize(encoder: Encoder, value: Point3D) { override fun serialize(encoder: Encoder, value: Point3D) {