Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass at a DOM Box implementation #1981

Draft
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ import org.w3c.dom.HTMLElement
public class HTMLElementRedwoodLayoutWidgetFactory(
private val document: Document,
) : RedwoodLayoutWidgetFactory<HTMLElement> {
override fun Box(): Box<HTMLElement> {
TODO("Not yet implemented")
}
override fun Box(): Box<HTMLElement> =
HTMLBoxContainer(
value = document.createElement("div") as HTMLDivElement,
)

override fun Column(): Column<HTMLElement> =
HTMLFlexContainer(
Expand All @@ -68,6 +69,41 @@ public class HTMLElementRedwoodLayoutWidgetFactory(
)
}

private class HTMLBoxContainer(
override val value: HTMLDivElement
) : Box<HTMLElement> {
override val children: Widget.Children<HTMLElement> = HTMLBoxChildren(value)

override fun width(width: Constraint) {
value.style.width = width.toCss()
}

override fun height(height: Constraint) {
value.style.height = height.toCss()
}

override fun margin(margin: Margin) {
value.style.apply {
marginInlineStart = margin.start.toPxString()
marginInlineEnd = margin.end.toPxString()
marginTop = margin.top.toPxString()
marginBottom = margin.bottom.toPxString()
}
}

// TODO: Make CrossAxisAlignment.Stretch work
override fun horizontalAlignment(horizontalAlignment: CrossAxisAlignment) {
value.style.justifyContent = horizontalAlignment.toCss()
}

// TODO: Make CrossAxisAlignment.Stretch work
override fun verticalAlignment(verticalAlignment: CrossAxisAlignment) {
value.style.alignItems = verticalAlignment.toCss()
}

override var modifier: Modifier = Modifier
}

private class HTMLFlexContainer(
override val value: HTMLDivElement,
direction: String,
Expand Down Expand Up @@ -126,6 +162,37 @@ private class HTMLSpacer(
override var modifier: Modifier = Modifier
}

private class HTMLBoxChildren(
private val container: HTMLElement,
private val delegate: HTMLElementChildren = HTMLElementChildren(container),
) : Widget.Children<HTMLElement> by delegate {
override fun insert(index: Int, widget: Widget<HTMLElement>) {
widget.applyModifiers(clearStyles = false)
// Use absolute positioning as a hack to make items overlap
widget.value.style.position = "absolute"
delegate.insert(index, widget)
}

override fun onModifierUpdated(index: Int, widget: Widget<HTMLElement>) {
widget.applyModifiers(clearStyles = true)
delegate.onModifierUpdated(index, widget)
}

private fun Widget<HTMLElement>.applyModifiers(clearStyles: Boolean) {
if (clearStyles) {
value.removeModifierStyles()
}

modifier.forEachScoped { element ->
when (element) {
is MarginModifier -> {
element.applyTo(value)
}
}
}
}
}

private class HTMLFlexElementChildren(
private val container: HTMLElement,
private val delegate: HTMLElementChildren = HTMLElementChildren(container),
Expand All @@ -143,28 +210,13 @@ private class HTMLFlexElementChildren(

private fun Widget<HTMLElement>.applyModifiers(clearStyles: Boolean) {
if (clearStyles) {
value.style.apply {
removeProperty("margin-inline-start")
removeProperty("margin-inline-end")
removeProperty("margin-top")
removeProperty("margin-bottom")
removeProperty("flex-grow")
removeProperty("flex-shrink")
removeProperty("flex")
removeProperty("width")
removeProperty("height")
}
value.removeModifierStyles()
}

modifier.forEachScoped { element ->
when (element) {
is MarginModifier -> {
value.style.apply {
marginInlineStart = element.margin.start.toPxString()
marginInlineEnd = element.margin.end.toPxString()
marginTop = element.margin.top.toPxString()
marginBottom = element.margin.bottom.toPxString()
}
element.applyTo(value)
}
is Grow -> value.style.apply {
flexGrow = element.value.toString()
Expand All @@ -189,3 +241,29 @@ private class HTMLFlexElementChildren(
}
}
}

private fun MarginModifier.applyTo(element: HTMLElement) {
val theMargin = margin
with (margin) {
element.style.apply {
marginInlineStart = theMargin.start.toPxString()
marginInlineEnd = theMargin.end.toPxString()
marginTop = theMargin.top.toPxString()
marginBottom = theMargin.bottom.toPxString()
}
}
}

private fun HTMLElement.removeModifierStyles() {
style.apply {
removeProperty("margin-inline-start")
removeProperty("margin-inline-end")
removeProperty("margin-top")
removeProperty("margin-bottom")
removeProperty("flex-grow")
removeProperty("flex-shrink")
removeProperty("flex")
removeProperty("width")
removeProperty("height")
}
}
Loading