diff --git a/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainer.kt b/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainer.kt index 80308ccd74..81b6f23bc9 100644 --- a/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainer.kt +++ b/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainer.kt @@ -17,9 +17,14 @@ package app.cash.redwood.layout.uiview import app.cash.redwood.Modifier import app.cash.redwood.layout.api.Constraint +import app.cash.redwood.layout.api.CrossAxisAlignment +import app.cash.redwood.layout.api.MainAxisAlignment import app.cash.redwood.layout.api.Overflow +import app.cash.redwood.layout.widget.Column +import app.cash.redwood.layout.widget.Row import app.cash.redwood.ui.Default import app.cash.redwood.ui.Density +import app.cash.redwood.ui.Margin import app.cash.redwood.ui.Px import app.cash.redwood.widget.ChangeListener import app.cash.redwood.widget.ResizableWidget @@ -31,15 +36,61 @@ import kotlinx.cinterop.convert import platform.UIKit.UIView import platform.darwin.NSInteger -internal class UIViewFlexContainer( - direction: FlexDirection, -) : YogaFlexContainer, +internal class UIViewColumn : + Column, ResizableWidget, ChangeListener { - private val yogaView: YogaUIView = YogaUIView() + private val container = UIViewFlexContainer(FlexDirection.Column) + + override val value: UIView get() = container.value + override var modifier by container::modifier + override val children get() = container.children + override var sizeListener by container::sizeListener + + override fun width(width: Constraint) = container.width(width) + override fun height(height: Constraint) = container.height(height) + override fun margin(margin: Margin) = container.margin(margin) + override fun overflow(overflow: Overflow) = container.overflow(overflow) + override fun horizontalAlignment(horizontalAlignment: CrossAxisAlignment) = container.crossAxisAlignment(horizontalAlignment) + override fun verticalAlignment(verticalAlignment: MainAxisAlignment) = container.mainAxisAlignment(verticalAlignment) + override fun onScroll(onScroll: ((Px) -> Unit)?) = container.onScroll(onScroll) + override fun onEndChanges() = container.onEndChanges() +} + +internal class UIViewRow : + Row, + ResizableWidget, + ChangeListener { + private val container = UIViewFlexContainer(FlexDirection.Row) + + override val value: UIView get() = container.value + override var modifier by container::modifier + override val children get() = container.children + override var sizeListener by container::sizeListener + + override fun width(width: Constraint) = container.width(width) + override fun height(height: Constraint) = container.height(height) + override fun margin(margin: Margin) = container.margin(margin) + override fun overflow(overflow: Overflow) = container.overflow(overflow) + override fun horizontalAlignment(horizontalAlignment: MainAxisAlignment) = container.mainAxisAlignment(horizontalAlignment) + override fun verticalAlignment(verticalAlignment: CrossAxisAlignment) = container.crossAxisAlignment(verticalAlignment) + override fun onScroll(onScroll: ((Px) -> Unit)?) = container.onScroll(onScroll) + override fun onEndChanges() = container.onEndChanges() +} + +internal class UIViewFlexContainer( + direction: FlexDirection, +) : YogaFlexContainer { + private val yogaView: YogaUIView = YogaUIView().apply { + rootNode.flexDirection = direction + } + override val rootNode: Node get() = yogaView.rootNode override val density: Density get() = Density.Default + override val value: UIView get() = yogaView + override var modifier: Modifier = Modifier + override val children: UIViewChildren = UIViewChildren( container = value, insert = { index, widget -> @@ -68,13 +119,8 @@ internal class UIViewFlexContainer( }, invalidateSize = ::invalidateSize, ) - override var modifier: Modifier = Modifier - override var sizeListener: SizeListener? = null - - init { - yogaView.rootNode.flexDirection = direction - } + var sizeListener: SizeListener? = null override fun width(width: Constraint) { yogaView.widthConstraint = width @@ -92,7 +138,7 @@ internal class UIViewFlexContainer( yogaView.onScroll = onScroll } - override fun onEndChanges() { + fun onEndChanges() { invalidateSize() } diff --git a/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewRedwoodLayoutWidgetFactory.kt b/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewRedwoodLayoutWidgetFactory.kt index 1cbb7651ff..7a35e87a59 100644 --- a/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewRedwoodLayoutWidgetFactory.kt +++ b/redwood-layout-uiview/src/commonMain/kotlin/app/cash/redwood/layout/uiview/UIViewRedwoodLayoutWidgetFactory.kt @@ -20,13 +20,12 @@ import app.cash.redwood.layout.widget.Column import app.cash.redwood.layout.widget.RedwoodLayoutWidgetFactory import app.cash.redwood.layout.widget.Row import app.cash.redwood.layout.widget.Spacer -import app.cash.redwood.yoga.FlexDirection import platform.UIKit.UIView @ObjCName("UIViewRedwoodLayoutWidgetFactory", exact = true) public class UIViewRedwoodLayoutWidgetFactory : RedwoodLayoutWidgetFactory { override fun Box(): Box = UIViewBox() - override fun Column(): Column = UIViewFlexContainer(FlexDirection.Column) - override fun Row(): Row = UIViewFlexContainer(FlexDirection.Row) + override fun Column(): Column = UIViewColumn() + override fun Row(): Row = UIViewRow() override fun Spacer(): Spacer = UIViewSpacer() } diff --git a/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainerTest.kt b/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainerTest.kt index dd39353108..e5403eadad 100644 --- a/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainerTest.kt +++ b/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewFlexContainerTest.kt @@ -20,13 +20,15 @@ import app.cash.redwood.layout.AbstractFlexContainerTest import app.cash.redwood.layout.TestFlexContainer import app.cash.redwood.layout.api.Constraint import app.cash.redwood.layout.api.CrossAxisAlignment +import app.cash.redwood.layout.api.Overflow +import app.cash.redwood.layout.widget.Column +import app.cash.redwood.layout.widget.Row import app.cash.redwood.layout.widget.Spacer import app.cash.redwood.snapshot.testing.UIViewSnapshotCallback import app.cash.redwood.snapshot.testing.UIViewSnapshotter import app.cash.redwood.snapshot.testing.UIViewTestWidgetFactory import app.cash.redwood.snapshot.testing.toUIColor import app.cash.redwood.ui.Px -import app.cash.redwood.widget.ChangeListener import app.cash.redwood.widget.ResizableWidget import app.cash.redwood.widget.ResizableWidget.SizeListener import app.cash.redwood.widget.Widget @@ -66,9 +68,15 @@ class UIViewFlexContainerTest( } } - override fun row() = flexContainer(FlexDirection.Row) + override fun row(): Row = UIViewRow().apply { + value.backgroundColor = defaultBackgroundColor.toUIColor() + applyDefaults() + } - override fun column() = flexContainer(FlexDirection.Column) + override fun column(): Column = UIViewColumn().apply { + value.backgroundColor = defaultBackgroundColor.toUIColor() + applyDefaults() + } override fun spacer(backgroundColor: Int): Spacer { return UIViewRedwoodLayoutWidgetFactory().Spacer() @@ -81,11 +89,15 @@ class UIViewFlexContainerTest( private val delegate: UIViewFlexContainer, ) : TestFlexContainer, ResizableWidget, - YogaFlexContainer by delegate, - ChangeListener by delegate { + YogaFlexContainer by delegate { override var sizeListener: SizeListener? by delegate::sizeListener - override val children: Widget.Children = delegate.children + override val value: UIView get() = delegate.value + override var modifier by delegate::modifier + override val children: Widget.Children get() = delegate.children + override fun width(width: Constraint) = delegate.width(width) + override fun height(height: Constraint) = delegate.height(height) + override fun overflow(overflow: Overflow) = delegate.overflow(overflow) init { value.backgroundColor = UIColor(red = 0.0, green = 0.0, blue = 1.0, alpha = 0.2) @@ -98,6 +110,8 @@ class UIViewFlexContainerTest( override fun scroll(offset: Px) { (delegate.value as UIScrollView).setContentOffset(cValue { y = offset.value }, false) } + + override fun onEndChanges() = delegate.onEndChanges() } override fun snapshotter(widget: UIView) = UIViewSnapshotter.framed(callback, widget)