Skip to content

Commit

Permalink
Merge pull request #27 from InkApplications/static-html
Browse files Browse the repository at this point in the history
Static HTML layouts and formatted text
  • Loading branch information
ReneeVandervelde authored Aug 25, 2024
2 parents 4970cc4 + 9e5bb48 commit 797e645
Show file tree
Hide file tree
Showing 82 changed files with 718 additions and 479 deletions.
1 change: 1 addition & 0 deletions render-compose-html/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ kotlin {
implementation(compose.runtime)
implementation(libs.kotlinx.coroutines.core)
api(projects.structures)
implementation(projects.renderWebCommon)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package ink.ui.render.compose.html
import androidx.compose.runtime.Composable
import ink.ui.render.compose.html.renderer.*
import ink.ui.render.compose.html.renderer.CompositeElementRenderer
import ink.ui.render.web.gridTemplateColumns
import ink.ui.structures.Positioning
import ink.ui.structures.elements.UiElement
import ink.ui.structures.layouts.*
import ink.ui.structures.render.RenderResult
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.Section
Expand Down Expand Up @@ -41,7 +43,7 @@ class HtmlComposeRenderer(
attrs = {
classes("fixed-grid")
style {
gridTemplateColumns((0 until uiLayout.columns).joinToString(" ") { "auto" })
gridTemplateColumns(uiLayout.gridTemplateColumns)
}
}
) {
Expand All @@ -50,7 +52,6 @@ class HtmlComposeRenderer(
attrs = {
style {
gridColumn("span ${it.span}")
display(DisplayStyle.Flex)
when (it.horizontalPositioning) {
Positioning.Start -> {
justifyContent(JustifyContent.Start)
Expand Down Expand Up @@ -95,8 +96,9 @@ class HtmlComposeRenderer(

@Composable
fun renderElement(element: UiElement) {
when (uiRenderer.render(element, uiRenderer)) {
RenderResult.NotRendered -> throw IllegalArgumentException("No renderer registered for ${element::class.simpleName}")
when (val result = uiRenderer.render(element, uiRenderer)) {
RenderResult.Skipped -> throw IllegalArgumentException("No renderer registered for ${element::class.simpleName}")
is RenderResult.Failed -> throw result.exception
RenderResult.Rendered -> {}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.*
import ink.ui.render.web.toCssClass
import ink.ui.structures.Sentiment
import ink.ui.structures.elements.ProgressElement
import ink.ui.structures.elements.ThrobberElement
import ink.ui.structures.elements.UiElement
import ink.ui.structures.render.RenderResult
import kotlinx.coroutines.delay
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.*
Expand All @@ -18,7 +20,7 @@ object ActivityRenderer: ElementRenderer {
when (element) {
is ProgressElement -> ProgressBar(element)
is ThrobberElement -> Throbber(element.caption, element.sentiment)
else -> return RenderResult.NotRendered
else -> return RenderResult.Skipped
}

return RenderResult.Rendered
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,30 @@
package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.Composable
import ink.ui.render.web.svgSrc
import ink.ui.render.web.toCssClass
import ink.ui.structures.elements.ButtonElement
import ink.ui.structures.elements.UiElement
import org.jetbrains.compose.web.dom.Button
import org.jetbrains.compose.web.dom.Img
import org.jetbrains.compose.web.dom.Text

object ButtonRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
if (element !is ButtonElement) return RenderResult.NotRendered

Button(
attrs = {
classes(element.sentiment.toCssClass())
onClick {
element.onClick()
}
}
) {
val leadingSymbol = element.leadingSymbol
if (leadingSymbol != null) {
Img(
attrs = {
classes("icon", "svg-fill", element.sentiment.toCssClass())
},
src = leadingSymbol.svgSrc,
)
val ButtonRenderer = renderer<ButtonElement> { element ->
Button(
attrs = {
classes(element.sentiment.toCssClass())
onClick {
element.onClick()
}
Text(element.text)
}

return RenderResult.Rendered
) {
val leadingSymbol = element.leadingSymbol
if (leadingSymbol != null) {
Img(
attrs = {
classes("icon", "svg-fill", element.sentiment.toCssClass())
},
src = leadingSymbol.svgSrc,
)
}
Text(element.text)
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.Composable
import ink.ui.structures.elements.CheckBoxElement
import ink.ui.structures.elements.UiElement
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.dom.Input

object CheckBoxRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
if (element !is CheckBoxElement) return RenderResult.NotRendered

Input(
type = InputType.Checkbox,
attrs = {
onClick { element.onClick() }
checked(element.checked)
}
)

return RenderResult.Rendered
}
val CheckBoxRenderer = renderer<CheckBoxElement> { element ->
Input(
type = InputType.Checkbox,
attrs = {
onClick { element.onClick() }
checked(element.checked)
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.Composable
import ink.ui.structures.elements.UiElement
import ink.ui.structures.render.RenderResult
import ink.ui.structures.render.renderCatching

internal class CompositeElementRenderer(
private val renderers: List<ElementRenderer> = emptyList(),
): ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
renderers.forEach { renderer ->
if (renderer.render(element, this) == RenderResult.Rendered) {
return RenderResult.Rendered
val result = renderCatching { renderer.render(element, this) }

if (result != RenderResult.Skipped) {
return result
}
}
return RenderResult.NotRendered
return RenderResult.Skipped
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.Composable
import ink.ui.structures.elements.UiElement
import ink.ui.structures.render.RenderResult
import ink.ui.structures.render.renderCatching

/**
* Renders a UI element in compose.
Expand All @@ -13,3 +15,19 @@ interface ElementRenderer {
parent: ElementRenderer
): RenderResult
}

inline fun <reified T: UiElement> renderer(
crossinline render: @Composable (element: T) -> Unit
): ElementRenderer = object: ElementRenderer {
@Composable
override fun render(
element: UiElement,
parent: ElementRenderer
): RenderResult {
if (element !is T) return RenderResult.Skipped
return renderCatching {
render(element)
RenderResult.Rendered
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.Composable
import ink.ui.structures.elements.EmptyElement
import ink.ui.structures.elements.UiElement
import org.jetbrains.compose.web.dom.Span

object EmptyRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
if (element !is EmptyElement) return RenderResult.NotRendered

val EmptyRenderer = renderer<EmptyElement> { element ->
Span {}

return RenderResult.Rendered
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
package ink.ui.render.compose.html.renderer

import androidx.compose.runtime.Composable
import ink.ui.render.web.svgSrc
import ink.ui.render.web.toCssClass
import ink.ui.structures.elements.IconElement
import ink.ui.structures.elements.UiElement
import org.jetbrains.compose.web.dom.Img

object IconRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
if (element !is IconElement) return RenderResult.NotRendered

Img(
src = element.symbol.svgSrc,
attrs = {
classes("icon", "svg-fill", element.sentiment.toCssClass())
}
)

return RenderResult.Rendered
}
val IconRenderer = renderer<IconElement> { element ->
Img(
src = element.symbol.svgSrc,
attrs = {
classes("icon", "svg-fill", element.sentiment.toCssClass())
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import ink.ui.structures.GroupingStyle
import ink.ui.structures.Positioning
import ink.ui.structures.elements.ElementList
import ink.ui.structures.elements.UiElement
import ink.ui.structures.render.RenderResult
import org.jetbrains.compose.web.css.JustifyContent
import org.jetbrains.compose.web.css.justifyContent
import org.jetbrains.compose.web.dom.Div

object ListRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
if (element !is ElementList) return RenderResult.NotRendered
if (element !is ElementList) return RenderResult.Skipped

Div(
attrs = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package ink.ui.render.compose.html.renderer
import androidx.compose.runtime.Composable
import ink.ui.structures.elements.MenuRowElement
import ink.ui.structures.elements.UiElement
import ink.ui.structures.render.RenderResult
import org.jetbrains.compose.web.dom.*

object MenuRowRenderer: ElementRenderer {
@Composable
override fun render(element: UiElement, parent: ElementRenderer): RenderResult {
if (element !is MenuRowElement) return RenderResult.NotRendered
if (element !is MenuRowElement) return RenderResult.Skipped
val elementOnClick = element.onClick
Div(
attrs = {
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 797e645

Please sign in to comment.