From 59e0bc45954aa7e3056f4be8dc62927c934a8c5d Mon Sep 17 00:00:00 2001 From: "marc." Date: Fri, 26 Apr 2024 15:58:14 +0200 Subject: [PATCH] group widget and stack --- .../neptuneclient/voidui/framework/Widget.kt | 51 +++++++++++++++++++ .../com/neptuneclient/voidui/widgets/Stack.kt | 32 ++++++++++++ .../neptuneclient/voidui/tests/ScreenTest.kt | 25 ++++++++- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/com/neptuneclient/voidui/widgets/Stack.kt diff --git a/src/main/kotlin/com/neptuneclient/voidui/framework/Widget.kt b/src/main/kotlin/com/neptuneclient/voidui/framework/Widget.kt index 0061fb0..18e269f 100644 --- a/src/main/kotlin/com/neptuneclient/voidui/framework/Widget.kt +++ b/src/main/kotlin/com/neptuneclient/voidui/framework/Widget.kt @@ -179,4 +179,55 @@ abstract class LeafWidget : Widget() { voidUI.eventHandler.unregister(this) } +} + +/** + * A special type of widget which contains multiple child widgets instead of just one. + */ +abstract class GroupWidget : Widget() { + + /** + * The children of the group widget. + */ + protected lateinit var roots: Array + + override fun init(screen: Screen, parent: Widget) { + this.voidUI = screen.voidUI + this.screen = screen + + roots = buildGroup() + roots.forEach { it.init(screen, this) } + } + + /** + * Since it is not clear how group widgets position their children, they need to define the layout themselves. + */ + abstract override fun layout(constraints: BoxConstraints) + + override fun postLayoutInit(parentOffset: Offset, parent: Widget) { + offset = parentOffset + + val renderable = createRenderObject() + if (renderable != null) + screen.renderStack.push(renderable) + + roots.forEach { it.postLayoutInit(parentOffset, this) } + } + + override fun remove() { + roots.forEach { it.remove() } + } + + /** + * Returns an array of widgets, which build the widget tree. + */ + abstract fun buildGroup(): Array + + /** + * The build method from the widget is not called on group widgets. + */ + override fun build(): Widget { + return Placeholder() + } + } \ No newline at end of file diff --git a/src/main/kotlin/com/neptuneclient/voidui/widgets/Stack.kt b/src/main/kotlin/com/neptuneclient/voidui/widgets/Stack.kt new file mode 100644 index 0000000..94474cb --- /dev/null +++ b/src/main/kotlin/com/neptuneclient/voidui/widgets/Stack.kt @@ -0,0 +1,32 @@ +package com.neptuneclient.voidui.widgets + +import com.neptuneclient.voidui.framework.BoxConstraints +import com.neptuneclient.voidui.framework.GroupWidget +import com.neptuneclient.voidui.framework.Size +import com.neptuneclient.voidui.framework.Widget +import kotlin.math.max + +/** + * A widget which layers multiple widgets on top of each other. + * + * @param children The array of children in the stack. + */ +class Stack(private val children: Array) : GroupWidget() { + + override fun layout(constraints: BoxConstraints) { + var childWidth = 0f + var childHeight = 0f + + children.forEach { + it.layout(constraints) + childWidth = max(childWidth, it.size.width) + childHeight = max(childHeight, it.size.height) + } + size = constraints.constrain(Size(childWidth, childHeight)) + } + + override fun buildGroup(): Array { + return children + } + +} \ No newline at end of file diff --git a/src/test/kotlin/com/neptuneclient/voidui/tests/ScreenTest.kt b/src/test/kotlin/com/neptuneclient/voidui/tests/ScreenTest.kt index 552816d..9309d2e 100644 --- a/src/test/kotlin/com/neptuneclient/voidui/tests/ScreenTest.kt +++ b/src/test/kotlin/com/neptuneclient/voidui/tests/ScreenTest.kt @@ -6,7 +6,11 @@ import com.neptuneclient.voidui.VoidUI import com.neptuneclient.voidui.event.MouseClickedEvent import com.neptuneclient.voidui.event.MouseReleasedEvent import com.neptuneclient.voidui.framework.Screen +import com.neptuneclient.voidui.framework.Size import com.neptuneclient.voidui.framework.Widget +import com.neptuneclient.voidui.objects.Border +import com.neptuneclient.voidui.objects.EdgeInsets +import com.neptuneclient.voidui.utils.image import com.neptuneclient.voidui.widgets.* import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable import org.lwjgl.glfw.GLFW @@ -15,7 +19,26 @@ import java.awt.Color class TestScreen(voidUI: VoidUI) : Screen(voidUI) { override fun build(): Widget { - return Placeholder() + return Container( + margin = EdgeInsets.all(100f), + border = Border(2f, Color.RED), + child = Stack( + children = arrayOf( + Image( + src = image("images/hampter.png"), + imageSize = Size( + width = 200f, + height = 200f + ) + ), + Container( + color = Color.GREEN, + padding = EdgeInsets.symmetric(horizontal = 120f), + child = Text("Hello World!") + ) + ) + ) + ) } }