Skip to content

Commit

Permalink
refactor compose-html
Browse files Browse the repository at this point in the history
  • Loading branch information
altavir committed Feb 12, 2024
1 parent 38d6a9c commit d90c1ed
Show file tree
Hide file tree
Showing 21 changed files with 143 additions and 88 deletions.
6 changes: 4 additions & 2 deletions demo/muon-monitor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ kscience {

commonMain {
implementation(projects.visionforgeSolid)
implementation(projects.visionforgeComposeHtml)
}
jvmMain {
implementation("org.apache.commons:commons-math3:3.6.1")
Expand All @@ -40,12 +39,15 @@ kscience {
implementation("ch.qos.logback:logback-classic:1.2.11")
}
jsMain {
// implementation(projects.visionforgeComposeHtml)
implementation(projects.visionforgeThreejs)
//implementation(devNpm("webpack-bundle-analyzer", "4.4.0"))
}
}
kotlin{
explicitApi = null
}

kotlin.explicitApi = null

application {
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
Expand Down
20 changes: 9 additions & 11 deletions visionforge-compose-html/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ plugins {
}

kscience {
jvm()
js()
// wasm()
jvm()
}

kotlin {
Expand All @@ -15,23 +14,22 @@ kotlin {
commonMain {
dependencies {
api(projects.visionforgeCore)
api(compose.runtime)
}
}

val jvmMain by getting {
dependencies {
api(compose.foundation)
api(compose.material)
api(compose.preview)
jvmMain{
//need this to placate compose compiler in MPP applications
dependencies{
api(compose.runtime)
}
}

val jsMain by getting {
jsMain{
dependencies {
api(compose.html.core)
api("app.softwork:bootstrap-compose:0.1.15")
api("app.softwork:bootstrap-compose-icons:0.1.15")

api(compose.runtime)
api(compose.html.core)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@ import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionClient

/**
* An [ElementVisionRenderer] that could be used directly in Compose-html as well as a stand-alone renderer
*/
public interface ComposeVisionRenderer: ElementVisionRenderer {
public interface ComposeHtmlVisionRenderer : ElementVisionRenderer {

@Composable
public fun DOMScope<Element>.render(client: VisionClient, name: Name, vision: Vision, meta: Meta)
public fun DOMScope<Element>.render(name: Name, vision: Vision, meta: Meta)

override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
renderComposable(element) {
Style(VisionForgeStyles)
render(client, name, vision, meta)
render(name, vision, meta)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public fun Vision(
}

DisposableEffect(vision, name, renderer, meta) {
renderer.render(scopeElement, client, name, vision, meta)
renderer.render(scopeElement, name, vision, meta)
onDispose {
scopeElement.clear()
}
Expand Down
6 changes: 5 additions & 1 deletion visionforge-compose-mpp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {

kscience {
jvm()
wasm()
// wasm()
}

kotlin {
Expand All @@ -16,6 +16,10 @@ kotlin {
api(projects.visionforgeCore)
api(compose.runtime)
api(compose.foundation)
}
}
jvmMain{
dependencies{
api(compose.material)
api(compose.preview)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package space.kscience.visionforge.compose

import androidx.compose.runtime.Composable
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionClient

public interface ComposeVisionRenderer {
public fun rateVision(vision: Vision): Int
@Composable
public fun render(client: VisionClient, name: Name, vision: Vision, meta: Meta)

public companion object
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package space.kscience.visionforge.compose

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.Vision


/**
* Render an Element vision via injected vision renderer inside compose-html
*/
@Composable
public fun Vision(
context: Context,
vision: Vision,
name: Name = "@vision[${vision.hashCode().toString(16)}]".asName(),
meta: Meta = Meta.EMPTY,
modifier: Modifier = Modifier,
) {

}
2 changes: 1 addition & 1 deletion visionforge-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ kscience {
jvm()
js()
native()
// wasm()
wasm()
useCoroutines()
commonMain {
api("space.kscience:dataforge-context:$dataforgeVersion")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ package space.kscience.visionforge

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.parseAsName
Expand All @@ -23,6 +22,9 @@ public abstract class VisionControlEvent : VisionEvent, MetaRepr {
public interface ControlVision : Vision {
public val controlEventFlow: SharedFlow<VisionControlEvent>

/**
* Fire a [VisionControlEvent] on this [ControlVision]
*/
public suspend fun dispatchControlEvent(event: VisionControlEvent)

override suspend fun receiveEvent(event: VisionEvent) {
Expand All @@ -32,6 +34,28 @@ public interface ControlVision : Vision {
}
}

public fun ControlVision.asyncControlEvent(
event: VisionControlEvent,
scope: CoroutineScope = manager?.context ?: error("Can't fire asynchronous event for an orphan vision. Provide a scope."),
) {
scope.launch { dispatchControlEvent(event) }
}


@Serializable
public abstract class AbstractControlVision : AbstractVision(), ControlVision {

@Transient
private val mutableControlEventFlow = MutableSharedFlow<VisionControlEvent>()

override val controlEventFlow: SharedFlow<VisionControlEvent>
get() = mutableControlEventFlow

override suspend fun dispatchControlEvent(event: VisionControlEvent) {
mutableControlEventFlow.emit(event)
}
}


/**
* An event for submitting changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ package space.kscience.visionforge.html

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.html.DIV
import kotlinx.html.InputType
import kotlinx.html.div
import kotlinx.html.stream.createHTML
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.*


@Serializable
public abstract class VisionOfHtml : AbstractVision() {
public interface VisionOfHtml : Vision {
public var classes: Set<String>
get() = properties[::classes.name, false].stringList?.toSet() ?: emptySet()
set(value) {
Expand All @@ -26,7 +26,7 @@ public abstract class VisionOfHtml : AbstractVision() {

@Serializable
@SerialName("html.plain")
public class VisionOfPlainHtml : VisionOfHtml() {
public class VisionOfPlainHtml : AbstractVision(), VisionOfHtml {
public var content: String? by properties.string()
}

Expand Down Expand Up @@ -59,26 +59,11 @@ public enum class InputFeedbackMode {
NONE
}

@Serializable
public abstract class VisionOfHtmlControl: VisionOfHtml(), ControlVision{

@Transient
private val mutableControlEventFlow = MutableSharedFlow<VisionControlEvent>()

override val controlEventFlow: SharedFlow<VisionControlEvent>
get() = mutableControlEventFlow

override suspend fun dispatchControlEvent(event: VisionControlEvent) {
mutableControlEventFlow.emit(event)
}
}


@Serializable
@SerialName("html.input")
public open class VisionOfHtmlInput(
public val inputType: String,
) : VisionOfHtmlControl() {
) : AbstractControlVision(), VisionOfHtml {
public var value: Value? by properties.value()
public var disabled: Boolean by properties.boolean { false }
public var fieldName: String? by properties.string()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import kotlinx.serialization.Serializable
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.node
import space.kscience.dataforge.meta.string
import space.kscience.visionforge.AbstractControlVision
import space.kscience.visionforge.DataControl
import space.kscience.visionforge.onSubmit

Expand All @@ -18,7 +19,7 @@ import space.kscience.visionforge.onSubmit
@SerialName("html.form")
public class VisionOfHtmlForm(
public val formId: String,
) : VisionOfHtmlControl(), DataControl {
) : AbstractControlVision(), DataControl, VisionOfHtml {
public var values: Meta? by properties.node()
}

Expand All @@ -45,7 +46,7 @@ public fun VisionOfHtmlForm.onFormSubmit(scope: CoroutineScope, block: (Meta?) -

@Serializable
@SerialName("html.button")
public class VisionOfHtmlButton : VisionOfHtmlControl(), DataControl {
public class VisionOfHtmlButton : AbstractControlVision(), DataControl, VisionOfHtml {
public var label: String? by properties.string()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public interface ElementVisionRenderer {
*/
public fun render(
element: Element,
client: VisionClient,
name: Name,
vision: Vision,
meta: Meta = Meta.EMPTY,
Expand All @@ -49,27 +48,26 @@ public interface ElementVisionRenderer {
public class SingleTypeVisionRenderer<T : Vision>(
public val kClass: KClass<T>,
private val acceptRating: Int = ElementVisionRenderer.DEFAULT_RATING,
private val renderFunction: TagConsumer<HTMLElement>.(name: Name, client: VisionClient, vision: T, meta: Meta) -> Unit,
private val renderFunction: TagConsumer<HTMLElement>.(name: Name, vision: T, meta: Meta) -> Unit,
) : ElementVisionRenderer {

override fun rateVision(vision: Vision): Int =
if (vision::class == kClass) acceptRating else ElementVisionRenderer.ZERO_RATING

override fun render(
element: Element,
client: VisionClient,
name: Name,
vision: Vision,
meta: Meta,
) {
element.clear()
element.append {
renderFunction(name, client, kClass.cast(vision), meta)
renderFunction(name, kClass.cast(vision), meta)
}
}
}

public inline fun <reified T : Vision> ElementVisionRenderer(
acceptRating: Int = ElementVisionRenderer.DEFAULT_RATING,
noinline renderFunction: TagConsumer<HTMLElement>.(name: Name, client: VisionClient, vision: T, meta: Meta) -> Unit,
noinline renderFunction: TagConsumer<HTMLElement>.(name: Name, vision: T, meta: Meta) -> Unit,
): ElementVisionRenderer = SingleTypeVisionRenderer(T::class, acceptRating, renderFunction)
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ public class JsVisionClient : AbstractPlugin(), VisionClient {
vision.setAsRoot(visionManager)
val renderer: ElementVisionRenderer =
findRendererFor(vision) ?: error("Could not find renderer for ${vision::class}")
renderer.render(element, this, name, vision, outputMeta)
//subscribe to a backwards events propagation for control visions
if(vision is ControlVision){
vision.controlEventFlow.onEach {
sendEvent(name,it)
}.launchIn(context)
}
renderer.render(element, name, vision, outputMeta)
}

private fun startVisionUpdate(element: Element, visionName: Name, vision: Vision, outputMeta: Meta) {
Expand Down
Loading

0 comments on commit d90c1ed

Please sign in to comment.