diff --git a/korge-sandbox/src/commonMain/kotlin/Main.kt b/korge-sandbox/src/commonMain/kotlin/Main.kt index f0f4644b80..3bfa636572 100644 --- a/korge-sandbox/src/commonMain/kotlin/Main.kt +++ b/korge-sandbox/src/commonMain/kotlin/Main.kt @@ -135,10 +135,12 @@ suspend fun main() = Korge( //Demo(::MainColorTransformFilter), //Demo(::MainMasks), //Demo(::MainShape2dScene), - Demo(::MainSprites10k), + Demo(::MainUIStacks), + //Demo(::MainSprites10k), //Demo(::MainStressMatrixMultiplication), //Demo(::MainSDF), listOf( + Demo(::MainUIStacks), Demo(::MainShape2dScene), Demo(::MainStressMatrixMultiplication), Demo(::MainStressButtons), diff --git a/korge-sandbox/src/commonMain/kotlin/samples/MainUIStacks.kt b/korge-sandbox/src/commonMain/kotlin/samples/MainUIStacks.kt new file mode 100644 index 0000000000..10e5eea63c --- /dev/null +++ b/korge-sandbox/src/commonMain/kotlin/samples/MainUIStacks.kt @@ -0,0 +1,36 @@ +package samples + +import korlibs.image.color.* +import korlibs.korge.scene.* +import korlibs.korge.ui.* +import korlibs.korge.view.* + +class MainUIStacks : Scene() { + override suspend fun SContainer.sceneMain() { + lateinit var hs: UIHorizontalStack + lateinit var hs2: UIHorizontalStack + lateinit var hs3: UIHorizontalStack + uiVerticalStack { + hs = uiHorizontalStack { + solidRect(100, 100, Colors.BLUE) + solidRect(100, 120, Colors.RED) + solidRect(100, 100, Colors.GREEN) + solidRect(100, 100, Colors.YELLOW) + } + uiHorizontalStack { + solidRect(100, 100, Colors.YELLOW) + solidRect(100, 100, Colors.GREEN) + solidRect(100, 100, Colors.RED) + solidRect(100, 100, Colors.BLUE) + } + hs2 = uiHorizontalStack { + } + hs3 = uiHorizontalStack { + } + } + + hs.forcedHeight = 32f + hs2.solidRect(100, 100, Colors.BLUE) + hs3.solidRect(100, 100, Colors.YELLOW) + } +} diff --git a/korge/src/commonMain/kotlin/korlibs/korge/ui/UIContainerLayouts.kt b/korge/src/commonMain/kotlin/korlibs/korge/ui/UIContainerLayouts.kt index 05e7511a3a..caa3ab15fa 100644 --- a/korge/src/commonMain/kotlin/korlibs/korge/ui/UIContainerLayouts.kt +++ b/korge/src/commonMain/kotlin/korlibs/korge/ui/UIContainerLayouts.kt @@ -106,6 +106,7 @@ open class UIContainer(size: Size) : UIBaseContainer(size) { abstract class UIBaseContainer(size: Size) : UIView(size) { override fun onChildAdded(view: View) { + super.onChildAdded(view) relayout() } @@ -115,6 +116,7 @@ abstract class UIBaseContainer(size: Size) : UIView(size) { } override fun onSizeChanged() { + super.onSizeChanged() relayout() } @@ -132,44 +134,73 @@ abstract class UIBaseContainer(size: Size) : UIView(size) { } inline fun Container.uiVerticalStack( - width: Float = UI_DEFAULT_SIZE.width, + width: Float? = null, padding: Float = UI_DEFAULT_PADDING, adjustSize: Boolean = true, block: @ViewDslMarker UIVerticalStack.() -> Unit = {} ) = UIVerticalStack(width, padding, adjustSize).addTo(this).apply(block) open class UIVerticalStack( - width: Float = UI_DEFAULT_SIZE.width, + forcedWidth: Float? = null, padding: Float = UI_DEFAULT_PADDING, adjustSize: Boolean = true, -) : UIVerticalHorizontalStack(Size(width, 0f), padding, adjustSize) { +) : UIVerticalHorizontalStack(Size(forcedWidth ?: 100f, 0f), padding, adjustSize) { + var forcedWidth: Float? = forcedWidth + set(value) { + if (field != value) { + field = value + relayout() + //(parent as? UIContainer?)?.relayout() + } + } + override fun relayout() { var y = 0f + var bb = BoundsBuilder() forEachChild { it.y = y - if (adjustSize) it.scaledWidthD = widthD + if (adjustSize && forcedWidth != null) it.scaledWidthD = widthD y += it.height + padding + bb += it.getBounds(this@UIVerticalStack) } - unscaledHeight = y + unscaledSize = Size(if (forcedWidth == null) bb.xmax else forcedWidth!!, y) } } inline fun Container.uiHorizontalStack( - height: Float = UI_DEFAULT_SIZE.height, + height: Float? = null, padding: Float = UI_DEFAULT_PADDING, adjustHeight: Boolean = true, block: @ViewDslMarker UIHorizontalStack.() -> Unit = {} ) = UIHorizontalStack(height, padding, adjustHeight).addTo(this).apply(block) -open class UIHorizontalStack(height: Float = UI_DEFAULT_SIZE.height, padding: Float = UI_DEFAULT_PADDING, adjustHeight: Boolean = true) : UIVerticalHorizontalStack(Size(0f, height), padding, adjustHeight) { +open class UIHorizontalStack( + forcedHeight: Float? = null, + padding: Float = UI_DEFAULT_PADDING, + adjustHeight: Boolean = true +) : UIVerticalHorizontalStack(Size(0f, forcedHeight ?: 32f), padding, adjustHeight) { + var forcedHeight: Float? = forcedHeight + set(value) { + if (field != value) { + field = value + relayout() + //(parent as? UIContainer?)?.relayout() + } + } + override fun relayout() { var x = 0f + var bb = BoundsBuilder() forEachChild { it.x = x - if (adjustSize) it.scaledHeightD = heightD + if (adjustSize && forcedHeight != null) it.scaledHeightD = heightD x += it.width + padding + bb += it.getBounds(this@UIHorizontalStack) } - unscaledWidth = x + //println("forcedHeight=$forcedHeight!") + //val newUnscaledSize = + //println("UIHorizontalStack.relayout: unscaledSize=$unscaledSize, newUnscaledSize=$newUnscaledSize") + unscaledSize = Size(x, if (forcedHeight == null) bb.ymax else forcedHeight!!) } } diff --git a/korge/src/commonTest/kotlin/korlibs/korge/ui/UIContainerLayoutsTest.kt b/korge/src/commonTest/kotlin/korlibs/korge/ui/UIContainerLayoutsTest.kt new file mode 100644 index 0000000000..1e31fce46d --- /dev/null +++ b/korge/src/commonTest/kotlin/korlibs/korge/ui/UIContainerLayoutsTest.kt @@ -0,0 +1,56 @@ +package korlibs.korge.ui + +import korlibs.image.color.* +import korlibs.korge.view.* +import kotlin.test.* + +class UIContainerLayoutsTest { + @Test + fun test() { + val container = Container() + lateinit var hs1: UIHorizontalStack + lateinit var hs2: UIHorizontalStack + val vs = container.uiVerticalStack { + hs1 = uiHorizontalStack { + solidRect(100, 100, Colors.BLUE) + solidRect(100, 120, Colors.RED) + solidRect(100, 100, Colors.GREEN) + solidRect(100, 100, Colors.YELLOW) + } + hs2 = uiHorizontalStack { + solidRect(100, 100, Colors.YELLOW) + solidRect(100, 100, Colors.GREEN) + solidRect(100, 100, Colors.RED) + solidRect(100, 100, Colors.BLUE) + } + } + + assertEquals( + """ + Rectangle(x=0, y=0, width=400, height=220) + Rectangle(x=0, y=0, width=400, height=120) + Rectangle(x=0, y=120, width=400, height=100) + """.trimIndent(), + """ + ${vs.getBounds(container)} + ${hs1.getBounds(container)} + ${hs2.getBounds(container)} + """.trimIndent() + ) + + hs1.forcedHeight = 32f + + assertEquals( + """ + Rectangle(x=0, y=0, width=400, height=132) + Rectangle(x=0, y=0, width=400, height=32) + Rectangle(x=0, y=32, width=400, height=100) + """.trimIndent(), + """ + ${vs.getBounds(container)} + ${hs1.getBounds(container)} + ${hs2.getBounds(container)} + """.trimIndent() + ) + } +}