forked from kscience/visionforge
Non-nullable accessor for colors
This commit is contained in:
parent
64c447a37b
commit
399be206be
@ -7,7 +7,7 @@
|
||||
- Custom client-side events and thier processing in VisionServer
|
||||
|
||||
### Changed
|
||||
- Color accessor property is now `colorProperty`. Color uses `invoke` instead of `set`
|
||||
- Color accessor property is now `colorProperty`. Color uses non-nullable `invoke` instead of `set`.
|
||||
- API update for server and pages
|
||||
- Edges moved to solids module for easier construction
|
||||
- Visions **must** be rooted in order to subscribe to updates.
|
||||
|
@ -12,7 +12,7 @@ val fxVersion by extra("11")
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.3.0-dev-14"
|
||||
version = "0.3.0-dev-15"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -13,7 +13,6 @@ kscience {
|
||||
useKtor()
|
||||
fullStack(
|
||||
"muon-monitor.js",
|
||||
development = true,
|
||||
jvmConfig = { withJava() },
|
||||
jsConfig = { useCommonJs() }
|
||||
) {
|
||||
@ -47,9 +46,6 @@ application {
|
||||
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
|
||||
}
|
||||
|
||||
//TODO ???
|
||||
tasks.getByName("jsBrowserProductionWebpack").dependsOn("jsDevelopmentExecutableCompileSync")
|
||||
|
||||
//distributions {
|
||||
// main {
|
||||
// contents {
|
||||
|
@ -8,6 +8,6 @@ org.gradle.jvmargs=-Xmx4G
|
||||
|
||||
org.jetbrains.compose.experimental.jscanvas.enabled=true
|
||||
|
||||
toolsVersion=0.15.0-kotlin-1.9.20-RC2
|
||||
toolsVersion=0.15.0-kotlin-1.9.20
|
||||
#kotlin.experimental.tryK2=true
|
||||
#kscience.wasm.disabled=true
|
||||
|
41
ui/compose/build.gradle.kts
Normal file
41
ui/compose/build.gradle.kts
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
id("org.jetbrains.compose") version "1.5.10"
|
||||
// id("com.android.library")
|
||||
}
|
||||
|
||||
kscience{
|
||||
jvm()
|
||||
js()
|
||||
// wasm()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
// android()
|
||||
sourceSets {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
api(compose.runtime)
|
||||
api(compose.foundation)
|
||||
api(compose.material)
|
||||
api(compose.preview)
|
||||
}
|
||||
}
|
||||
|
||||
val jsMain by getting{
|
||||
dependencies {
|
||||
api(compose.html.core)
|
||||
api("app.softwork:bootstrap-compose:0.1.15")
|
||||
api("app.softwork:bootstrap-compose-icons:0.1.15")
|
||||
api(projects.visionforge.visionforgeThreejs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package space.kscience.visionforge.compose
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import kotlinx.html.js.onClickFunction
|
||||
import org.jetbrains.compose.web.css.AlignItems
|
||||
import org.jetbrains.compose.web.css.alignItems
|
||||
import org.jetbrains.compose.web.dom.Span
|
||||
import org.w3c.dom.events.Event
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.meta.descriptors.get
|
||||
import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.isLeaf
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.lastOrNull
|
||||
import space.kscience.dataforge.names.plus
|
||||
|
||||
|
||||
private val MetaViewerItem: FC<MetaViewerProps> = fc("MetaViewerItem") { props ->
|
||||
metaViewerItem(props)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MetaViewerItem(root: Meta, name: Name, rootDescriptor: MetaDescriptor? = null) {
|
||||
var expanded: Boolean by remember { mutableStateOf(true) }
|
||||
val item: Meta? = root[name]
|
||||
val descriptorItem: MetaDescriptor? = rootDescriptor?.get(name)
|
||||
val actualValue = item?.value ?: descriptorItem?.defaultValue
|
||||
val actualMeta = item ?: descriptorItem?.defaultNode
|
||||
|
||||
val token = name.lastOrNull()?.toString() ?: props.rootName ?: ""
|
||||
|
||||
val expanderClick: (Event) -> Unit = {
|
||||
expanded = !expanded
|
||||
}
|
||||
|
||||
FlexRow(attrs = {
|
||||
classes("metaItem")
|
||||
style {
|
||||
alignItems(AlignItems.Center)
|
||||
}
|
||||
}) {
|
||||
if (actualMeta?.isLeaf == false) {
|
||||
Span(attrs = {
|
||||
|
||||
})
|
||||
styledSpan {
|
||||
css {
|
||||
+TreeStyles.treeCaret
|
||||
if (expanded) {
|
||||
+TreeStyles.treeCaredDown
|
||||
}
|
||||
}
|
||||
attrs {
|
||||
onClickFunction = expanderClick
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
styledSpan {
|
||||
css {
|
||||
+TreeStyles.treeLabel
|
||||
if (item == null) {
|
||||
+TreeStyles.treeLabelInactive
|
||||
}
|
||||
}
|
||||
+token
|
||||
}
|
||||
styledDiv {
|
||||
a {
|
||||
+actualValue.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (expanded) {
|
||||
flexColumn {
|
||||
css {
|
||||
+TreeStyles.tree
|
||||
}
|
||||
val keys = buildSet {
|
||||
descriptorItem?.children?.keys?.forEach {
|
||||
add(NameToken(it))
|
||||
}
|
||||
actualMeta!!.items.keys.let { addAll(it) }
|
||||
}
|
||||
|
||||
keys.filter { !it.body.startsWith("@") }.forEach { token ->
|
||||
styledDiv {
|
||||
css {
|
||||
+TreeStyles.treeItem
|
||||
}
|
||||
child(MetaViewerItem) {
|
||||
attrs {
|
||||
this.key = props.name.toString()
|
||||
this.root = props.root
|
||||
this.name = props.name + token
|
||||
this.descriptor = props.descriptor
|
||||
}
|
||||
}
|
||||
//configEditor(props.root, props.name + token, props.descriptor, props.default)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@JsExport
|
||||
public val MetaViewer: FC<MetaViewerProps> = fc("MetaViewer") { props ->
|
||||
child(MetaViewerItem) {
|
||||
attrs {
|
||||
this.key = ""
|
||||
this.root = props.root
|
||||
this.name = Name.EMPTY
|
||||
this.descriptor = props.descriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun RBuilder.metaViewer(meta: Meta, descriptor: MetaDescriptor? = null, key: Any? = null) {
|
||||
child(MetaViewer) {
|
||||
attrs {
|
||||
this.key = key?.toString() ?: ""
|
||||
this.root = meta
|
||||
this.descriptor = descriptor
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package space.kscience.visionforge.compose
|
||||
|
||||
import kotlinx.css.*
|
||||
import org.jetbrains.compose.web.css.*
|
||||
|
||||
public object TreeStyles : StyleSheet() {
|
||||
/**
|
||||
* Remove default bullets
|
||||
*/
|
||||
public val tree: String by style {
|
||||
paddingLeft(5.px)
|
||||
marginLeft(0.px)
|
||||
listStyleType("none")
|
||||
}
|
||||
|
||||
/**
|
||||
* Style the caret/arrow
|
||||
*/
|
||||
public val treeCaret by style {
|
||||
cursor("pointer")
|
||||
userSelect = UserSelect.none
|
||||
/* Create the caret/arrow with a unicode, and style it */
|
||||
before {
|
||||
content = "\u25B6".quoted
|
||||
color(Color.black)
|
||||
display(DisplayStyle.InlineBlock)
|
||||
marginRight(6.px)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the caret/arrow icon when clicked on (using JavaScript)
|
||||
*/
|
||||
public val treeCaredDown by style {
|
||||
before {
|
||||
content = "\u25B6".quoted
|
||||
color(Color.black)
|
||||
display(DisplayStyle.InlineBlock)
|
||||
marginRight(6.px)
|
||||
transform { rotate(90.deg) }
|
||||
}
|
||||
}
|
||||
|
||||
public val treeItem: String by style {
|
||||
alignItems(AlignItems.Center)
|
||||
paddingLeft(10.px)
|
||||
border {
|
||||
left{
|
||||
width(1.px)
|
||||
color(Color.lightgray)
|
||||
style = LineStyle.Dashed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public val treeLabel by style {
|
||||
border(style = LineStyle.None)
|
||||
padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt)
|
||||
textAlign("left")
|
||||
flex(1)
|
||||
}
|
||||
|
||||
public val treeLabelInactive: RuleSet by css {
|
||||
color = Color.lightGray
|
||||
}
|
||||
|
||||
public val treeLabelSelected: RuleSet by css {
|
||||
backgroundColor = Color.lightBlue
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package space.kscience.visionforge.compose
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import org.jetbrains.compose.web.css.DisplayStyle
|
||||
import org.jetbrains.compose.web.css.FlexDirection
|
||||
import org.jetbrains.compose.web.css.display
|
||||
import org.jetbrains.compose.web.css.flexDirection
|
||||
import org.jetbrains.compose.web.dom.AttrBuilderContext
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
import org.jetbrains.compose.web.dom.ElementScope
|
||||
import org.w3c.dom.HTMLDivElement
|
||||
|
||||
@Composable
|
||||
public fun FlexColumn(
|
||||
attrs: AttrBuilderContext<HTMLDivElement>? = null,
|
||||
content: @Composable ElementScope<HTMLDivElement>.() -> Unit,
|
||||
): Unit = Div(
|
||||
attrs = {
|
||||
style {
|
||||
display(DisplayStyle.Flex)
|
||||
flexDirection(FlexDirection.Column)
|
||||
}
|
||||
attrs?.invoke(this)
|
||||
},
|
||||
content
|
||||
)
|
||||
|
||||
@Composable
|
||||
public fun FlexRow(
|
||||
attrs: AttrBuilderContext<HTMLDivElement>? = null,
|
||||
content: @Composable ElementScope<HTMLDivElement>.() -> Unit,
|
||||
): Unit = Div(
|
||||
attrs = {
|
||||
style {
|
||||
display(DisplayStyle.Flex)
|
||||
flexDirection(FlexDirection.Row)
|
||||
}
|
||||
attrs?.invoke(this)
|
||||
},
|
||||
content
|
||||
)
|
@ -34,33 +34,33 @@ public fun Vision.colorProperty(
|
||||
ColorAccessor(properties.root(true), propertyName ?: property.name.asName())
|
||||
}
|
||||
|
||||
public var ColorAccessor?.string: String?
|
||||
get() = this?.value?.let { if (it == Null) null else it.string }
|
||||
public var ColorAccessor.string: String?
|
||||
get() = value?.let { if (it == Null) null else it.string }
|
||||
set(value) {
|
||||
this?.value = value?.asValue()
|
||||
this.value = value?.asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(webColor: String) {
|
||||
this?.value = webColor.asValue()
|
||||
public operator fun ColorAccessor.invoke(webColor: String) {
|
||||
value = webColor.asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color as RGB integer
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(rgb: Int) {
|
||||
this?.value = Colors.rgbToString(rgb).asValue()
|
||||
public operator fun ColorAccessor.invoke(rgb: Int) {
|
||||
value = Colors.rgbToString(rgb).asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color as RGB
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(r: UByte, g: UByte, b: UByte) {
|
||||
this?.value = Colors.rgbToString(r, g, b).asValue()
|
||||
public operator fun ColorAccessor.invoke(r: UByte, g: UByte, b: UByte) {
|
||||
value = Colors.rgbToString(r, g, b).asValue()
|
||||
}
|
||||
|
||||
public fun ColorAccessor?.clear() {
|
||||
this?.value = null
|
||||
public fun ColorAccessor.clear() {
|
||||
value = null
|
||||
}
|
@ -94,7 +94,7 @@ class SolidPropertyTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
assertEquals("#555555", box?.color.string)
|
||||
assertEquals("#555555", box?.color?.string)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -31,7 +31,7 @@ class SolidReferenceTest {
|
||||
fun testReferenceSerialization(){
|
||||
val serialized = Solids.jsonForSolids.encodeToJsonElement(groupWithReference)
|
||||
val deserialized = Solids.jsonForSolids.decodeFromJsonElement(SolidGroup.serializer(), serialized)
|
||||
assertEquals(groupWithReference.items["test"]?.color.string, deserialized.items["test"]?.color.string)
|
||||
assertEquals(groupWithReference.items["test"]?.color?.string, deserialized.items["test"]?.color?.string)
|
||||
assertEquals("blue", (deserialized.children.getChild("test") as Solid).color.string)
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
}
|
||||
|
||||
val tablesVersion = "0.2.0-dev-4"
|
||||
val tablesVersion = "0.2.1"
|
||||
|
||||
kscience {
|
||||
jvm()
|
||||
@ -22,8 +22,8 @@ kscience {
|
||||
api("space.kscience:tables-kt:${tablesVersion}")
|
||||
}
|
||||
dependencies(jsMain) {
|
||||
implementation(npm("tabulator-tables", "5.4.4"))
|
||||
implementation(npm("@types/tabulator-tables", "5.4.8"))
|
||||
implementation(npm("tabulator-tables", "5.5.2"))
|
||||
implementation(npm("@types/tabulator-tables", "5.5.3"))
|
||||
}
|
||||
useSerialization()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user