From d21696626755a9ad655087f13c40ae4be9d7d2c9 Mon Sep 17 00:00:00 2001 From: Veyndan Stuart Date: Tue, 16 Jan 2024 16:52:33 +0100 Subject: [PATCH] Extract out common Yoga `FlexContainer` logic (#1378) --- .../redwood/buildsupport/flexboxHelpers.kt | 26 +++++++++++++++++ .../composeui/ComposeUiFlexContainer.kt | 19 ++++--------- .../layout/uiview/UIViewFlexContainer.kt | 27 ++---------------- .../redwood/layout/view/ViewFlexContainer.kt | 28 ++----------------- 4 files changed, 38 insertions(+), 62 deletions(-) diff --git a/build-support/src/main/resources/app/cash/redwood/buildsupport/flexboxHelpers.kt b/build-support/src/main/resources/app/cash/redwood/buildsupport/flexboxHelpers.kt index 19500efb95..f9366ae6e6 100644 --- a/build-support/src/main/resources/app/cash/redwood/buildsupport/flexboxHelpers.kt +++ b/build-support/src/main/resources/app/cash/redwood/buildsupport/flexboxHelpers.kt @@ -27,12 +27,38 @@ import app.cash.redwood.layout.modifier.Shrink as ShrinkModifier import app.cash.redwood.layout.modifier.Size as SizeModifier import app.cash.redwood.layout.modifier.VerticalAlignment as VerticalAlignmentModifier import app.cash.redwood.layout.modifier.Width as WidthModifier +import app.cash.redwood.layout.widget.FlexContainer import app.cash.redwood.ui.Density +import app.cash.redwood.ui.Margin import app.cash.redwood.yoga.AlignItems import app.cash.redwood.yoga.AlignSelf import app.cash.redwood.yoga.JustifyContent import app.cash.redwood.yoga.Node +internal interface YogaFlexContainer : FlexContainer { + val rootNode: Node + val density: Density + + override fun margin(margin: Margin) { + with(rootNode) { + with(density) { + marginStart = margin.start.toPx().toFloat() + marginEnd = margin.end.toPx().toFloat() + marginTop = margin.top.toPx().toFloat() + marginBottom = margin.bottom.toPx().toFloat() + } + } + } + + override fun crossAxisAlignment(crossAxisAlignment: CrossAxisAlignment) { + rootNode.alignItems = crossAxisAlignment.toAlignItems() + } + + override fun mainAxisAlignment(mainAxisAlignment: MainAxisAlignment) { + rootNode.justifyContent = mainAxisAlignment.toJustifyContent() + } +} + internal fun MainAxisAlignment.toJustifyContent() = when (this) { MainAxisAlignment.Start -> JustifyContent.FlexStart MainAxisAlignment.Center -> JustifyContent.Center diff --git a/redwood-layout-composeui/src/commonMain/kotlin/app/cash/redwood/layout/composeui/ComposeUiFlexContainer.kt b/redwood-layout-composeui/src/commonMain/kotlin/app/cash/redwood/layout/composeui/ComposeUiFlexContainer.kt index fe3c55e324..cefab72e8b 100644 --- a/redwood-layout-composeui/src/commonMain/kotlin/app/cash/redwood/layout/composeui/ComposeUiFlexContainer.kt +++ b/redwood-layout-composeui/src/commonMain/kotlin/app/cash/redwood/layout/composeui/ComposeUiFlexContainer.kt @@ -41,7 +41,6 @@ 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.FlexContainer import app.cash.redwood.ui.Density import app.cash.redwood.ui.Margin import app.cash.redwood.widget.compose.ComposeWidgetChildren @@ -53,8 +52,8 @@ import app.cash.redwood.yoga.isHorizontal internal class ComposeUiFlexContainer( private val flexDirection: FlexDirection, -) : FlexContainer<@Composable () -> Unit> { - private val rootNode = Node().apply { +) : YogaFlexContainer<@Composable () -> Unit> { + override val rootNode = Node().apply { flexDirection = this@ComposeUiFlexContainer.flexDirection } override val children = ComposeWidgetChildren() @@ -65,7 +64,7 @@ internal class ComposeUiFlexContainer( private var height by mutableStateOf(Constraint.Wrap) private var overflow by mutableStateOf(Overflow.Clip) private var margin by mutableStateOf(Margin.Zero) - private var density = Density(1.0) + override var density = Density(1.0) internal var testOnlyModifier: Modifier? = null @@ -86,12 +85,12 @@ internal class ComposeUiFlexContainer( } override fun crossAxisAlignment(crossAxisAlignment: CrossAxisAlignment) { - rootNode.alignItems = crossAxisAlignment.toAlignItems() + super.crossAxisAlignment(crossAxisAlignment) invalidate() } override fun mainAxisAlignment(mainAxisAlignment: MainAxisAlignment) { - rootNode.justifyContent = mainAxisAlignment.toJustifyContent() + super.mainAxisAlignment(mainAxisAlignment) invalidate() } @@ -112,14 +111,8 @@ internal class ComposeUiFlexContainer( LayoutDirection.Ltr -> Direction.LTR LayoutDirection.Rtl -> Direction.RTL } - - with(density) { - marginStart = margin.start.toPx().toFloat() - marginEnd = margin.end.toPx().toFloat() - marginTop = margin.top.toPx().toFloat() - marginBottom = margin.bottom.toPx().toFloat() - } } + super.margin(margin) children.render() }, 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 34fda77cb9..b1f822e4f0 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,13 +17,9 @@ 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.FlexContainer import app.cash.redwood.ui.Default import app.cash.redwood.ui.Density -import app.cash.redwood.ui.Margin import app.cash.redwood.widget.ChangeListener import app.cash.redwood.widget.UIViewChildren import app.cash.redwood.yoga.FlexDirection @@ -34,12 +30,14 @@ import platform.darwin.NSInteger internal class UIViewFlexContainer( direction: FlexDirection, -) : FlexContainer, ChangeListener { +) : YogaFlexContainer, ChangeListener { private val yogaView: YogaUIView = YogaUIView( applyModifier = { node, index -> node.applyModifier(children.widgets[index].modifier, Density.Default) }, ) + override val rootNode: Node get() = yogaView.rootNode + override val density: Density get() = Density.Default override val value: UIView get() = yogaView override val children = UIViewChildren( parent = value, @@ -68,29 +66,10 @@ internal class UIViewFlexContainer( yogaView.height = height } - override fun margin(margin: Margin) { - with(yogaView.rootNode) { - with(Density.Default) { - marginStart = margin.start.toPx().toFloat() - marginEnd = margin.end.toPx().toFloat() - marginTop = margin.top.toPx().toFloat() - marginBottom = margin.bottom.toPx().toFloat() - } - } - } - override fun overflow(overflow: Overflow) { yogaView.scrollEnabled = overflow == Overflow.Scroll } - override fun crossAxisAlignment(crossAxisAlignment: CrossAxisAlignment) { - yogaView.rootNode.alignItems = crossAxisAlignment.toAlignItems() - } - - override fun mainAxisAlignment(mainAxisAlignment: MainAxisAlignment) { - yogaView.rootNode.justifyContent = mainAxisAlignment.toJustifyContent() - } - override fun onEndChanges() { value.setNeedsLayout() } diff --git a/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewFlexContainer.kt b/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewFlexContainer.kt index 7e55183bec..09d5e930f6 100644 --- a/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewFlexContainer.kt +++ b/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewFlexContainer.kt @@ -27,12 +27,8 @@ import androidx.core.view.updateLayoutParams import androidx.core.widget.NestedScrollView 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.FlexContainer import app.cash.redwood.ui.Density -import app.cash.redwood.ui.Margin import app.cash.redwood.widget.ChangeListener import app.cash.redwood.widget.ViewGroupChildren import app.cash.redwood.yoga.Direction @@ -43,14 +39,15 @@ import app.cash.redwood.yoga.isHorizontal internal class ViewFlexContainer( private val context: Context, private val direction: FlexDirection, -) : FlexContainer, ChangeListener { +) : YogaFlexContainer, ChangeListener { private val yogaLayout: YogaLayout = YogaLayout( context, applyModifier = { node, index -> node.applyModifier(children.widgets[index].modifier, density) }, ) - private val density = Density(context.resources) + override val rootNode: Node get() = yogaLayout.rootNode + override val density = Density(context.resources) private val hostView = HostView() override val value: View get() = hostView @@ -90,17 +87,6 @@ internal class ViewFlexContainer( } } - override fun margin(margin: Margin) { - with(yogaLayout.rootNode) { - with(density) { - marginStart = margin.start.toPx().toFloat() - marginEnd = margin.end.toPx().toFloat() - marginTop = margin.top.toPx().toFloat() - marginBottom = margin.bottom.toPx().toFloat() - } - } - } - override fun overflow(overflow: Overflow) { hostView.scrollEnabled = when (overflow) { Overflow.Clip -> false @@ -109,14 +95,6 @@ internal class ViewFlexContainer( } } - override fun crossAxisAlignment(crossAxisAlignment: CrossAxisAlignment) { - yogaLayout.rootNode.alignItems = crossAxisAlignment.toAlignItems() - } - - override fun mainAxisAlignment(mainAxisAlignment: MainAxisAlignment) { - yogaLayout.rootNode.justifyContent = mainAxisAlignment.toJustifyContent() - } - override fun onEndChanges() { hostView.invalidate() hostView.requestLayout()