From 21e630278914fccb37286c06f5edfde7ec910ec0 Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Tue, 12 Nov 2024 14:14:02 -0500 Subject: [PATCH] Migrate View Row+Column away from subtype (#2442) When widgets switch to abstract classes, this will no longer be allowed. --- .../redwood/layout/view/ViewFlexContainer.kt | 47 ++++++++++++++++++- .../view/ViewRedwoodLayoutWidgetFactory.kt | 5 +- .../layout/view/ViewFlexContainerTest.kt | 26 +++++++--- 3 files changed, 67 insertions(+), 11 deletions(-) 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 c40e62a51f..3ffce45cb4 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,8 +27,13 @@ import androidx.core.widget.NestedScrollView import androidx.core.widget.NestedScrollView.OnScrollChangeListener as OnScrollChangeListenerCompat 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.Density +import app.cash.redwood.ui.Margin import app.cash.redwood.ui.Px import app.cash.redwood.widget.ChangeListener import app.cash.redwood.widget.ViewGroupChildren @@ -37,6 +42,46 @@ import app.cash.redwood.yoga.FlexDirection import app.cash.redwood.yoga.Node import app.cash.redwood.yoga.isHorizontal +internal class ViewColumn(context: Context) : + Column, + ChangeListener { + private val delegate = ViewFlexContainer(context, FlexDirection.Column) + + override val value get() = delegate.value + override var modifier by delegate::modifier + + override val children get() = delegate.children + + override fun width(width: Constraint) = delegate.width(width) + override fun height(height: Constraint) = delegate.height(height) + override fun margin(margin: Margin) = delegate.margin(margin) + override fun overflow(overflow: Overflow) = delegate.overflow(overflow) + override fun horizontalAlignment(horizontalAlignment: CrossAxisAlignment) = delegate.crossAxisAlignment(horizontalAlignment) + override fun verticalAlignment(verticalAlignment: MainAxisAlignment) = delegate.mainAxisAlignment(verticalAlignment) + override fun onScroll(onScroll: ((Px) -> Unit)?) = delegate.onScroll(onScroll) + override fun onEndChanges() = delegate.onEndChanges() +} + +internal class ViewRow(context: Context) : + Row, + ChangeListener { + private val delegate = ViewFlexContainer(context, FlexDirection.Row) + + override val value get() = delegate.value + override var modifier by delegate::modifier + + override val children get() = delegate.children + + override fun width(width: Constraint) = delegate.width(width) + override fun height(height: Constraint) = delegate.height(height) + override fun margin(margin: Margin) = delegate.margin(margin) + override fun overflow(overflow: Overflow) = delegate.overflow(overflow) + override fun horizontalAlignment(horizontalAlignment: MainAxisAlignment) = delegate.mainAxisAlignment(horizontalAlignment) + override fun verticalAlignment(verticalAlignment: CrossAxisAlignment) = delegate.crossAxisAlignment(verticalAlignment) + override fun onScroll(onScroll: ((Px) -> Unit)?) = delegate.onScroll(onScroll) + override fun onEndChanges() = delegate.onEndChanges() +} + internal class ViewFlexContainer( private val context: Context, private val direction: FlexDirection, @@ -73,7 +118,7 @@ internal class ViewFlexContainer( }, ) - private var onScroll: ((Px) -> Unit)? = null + internal var onScroll: ((Px) -> Unit)? = null override var modifier: Modifier = Modifier diff --git a/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewRedwoodLayoutWidgetFactory.kt b/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewRedwoodLayoutWidgetFactory.kt index 6f79e11866..972a975d1b 100644 --- a/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewRedwoodLayoutWidgetFactory.kt +++ b/redwood-layout-view/src/main/kotlin/app/cash/redwood/layout/view/ViewRedwoodLayoutWidgetFactory.kt @@ -22,16 +22,15 @@ 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 public class ViewRedwoodLayoutWidgetFactory( private val context: Context, ) : RedwoodLayoutWidgetFactory { override fun Box(): Box = ViewBox(context) - override fun Column(): Column = ViewFlexContainer(context, FlexDirection.Column) + override fun Column(): Column = ViewColumn(context) - override fun Row(): Row = ViewFlexContainer(context, FlexDirection.Row) + override fun Row(): Row = ViewRow(context) override fun Spacer(): Spacer = ViewSpacer(context) } diff --git a/redwood-layout-view/src/test/kotlin/app/cash/redwood/layout/view/ViewFlexContainerTest.kt b/redwood-layout-view/src/test/kotlin/app/cash/redwood/layout/view/ViewFlexContainerTest.kt index d0a1995346..8cee0a1eed 100644 --- a/redwood-layout-view/src/test/kotlin/app/cash/redwood/layout/view/ViewFlexContainerTest.kt +++ b/redwood-layout-view/src/test/kotlin/app/cash/redwood/layout/view/ViewFlexContainerTest.kt @@ -21,6 +21,10 @@ import app.cash.paparazzi.DeviceConfig import app.cash.paparazzi.Paparazzi 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.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.ViewSnapshotter import app.cash.redwood.snapshot.testing.ViewTestWidgetFactory @@ -57,9 +61,15 @@ class ViewFlexContainerTest( .apply { (this as TestFlexContainer<*>).applyDefaults() } } - override fun row() = flexContainer(FlexDirection.Row) + override fun row(): Row = ViewRow(paparazzi.context).apply { + value.setBackgroundColor(defaultBackgroundColor) + applyDefaults() + } - override fun column() = flexContainer(FlexDirection.Column) + override fun column(): Column = ViewColumn(paparazzi.context).apply { + value.setBackgroundColor(defaultBackgroundColor) + applyDefaults() + } override fun spacer(backgroundColor: Int): Spacer { return ViewSpacer(paparazzi.context) @@ -75,16 +85,18 @@ class ViewFlexContainerTest( ) : TestFlexContainer, YogaFlexContainer by delegate, ChangeListener by delegate { - private var onScroll: ((Px) -> Unit)? = null + override val value: View get() = delegate.value + override var modifier by delegate::modifier override val children: ViewGroupChildren = delegate.children - override fun onScroll(onScroll: ((Px) -> Unit)?) { - this.onScroll = onScroll - } + override fun width(width: Constraint) = delegate.width(width) + override fun height(height: Constraint) = delegate.height(height) + override fun overflow(overflow: Overflow) = delegate.overflow(overflow) + override fun onScroll(onScroll: ((Px) -> Unit)?) = delegate.onScroll(onScroll) override fun scroll(offset: Px) { - onScroll?.invoke(offset) + delegate.onScroll?.invoke(offset) } } }