From b90d50432650232fe8bd9fbd44146a5977248362 Mon Sep 17 00:00:00 2001 From: Chris Banes Date: Tue, 15 Oct 2024 13:34:59 +0100 Subject: [PATCH] Throw error on descendant layouts (#357) These have never been supported, but it has never been codified... before this PR. --- .../kotlin/dev/chrisbanes/haze/Haze.kt | 2 ++ .../dev/chrisbanes/haze/HazeChildNode.kt | 4 +++ .../kotlin/dev/chrisbanes/haze/HazeNode.kt | 31 ++++++++++--------- .../kotlin/dev/chrisbanes/haze/HazeTest.kt | 23 ++++++++++++++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/haze/src/commonMain/kotlin/dev/chrisbanes/haze/Haze.kt b/haze/src/commonMain/kotlin/dev/chrisbanes/haze/Haze.kt index 2e0328b5..d7b45f71 100644 --- a/haze/src/commonMain/kotlin/dev/chrisbanes/haze/Haze.kt +++ b/haze/src/commonMain/kotlin/dev/chrisbanes/haze/Haze.kt @@ -37,6 +37,8 @@ class HazeState { */ var contentLayer: GraphicsLayer? = null internal set + + internal var contentDrawing = false } /** diff --git a/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeChildNode.kt b/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeChildNode.kt index 5cd7b022..6217d5c3 100644 --- a/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeChildNode.kt +++ b/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeChildNode.kt @@ -87,6 +87,10 @@ internal class HazeChildNode( override fun ContentDrawScope.draw() { log(TAG) { "-> HazeChild. start draw()" } + require(!state.contentDrawing) { + "Layout nodes using Modifier.haze and Modifier.hazeChild can not be descendants of each other" + } + if (!effect.isValid) { // If we don't have any effects, just call drawContent and return early drawContent() diff --git a/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeNode.kt b/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeNode.kt index 40097b92..0de7bbb3 100644 --- a/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeNode.kt +++ b/haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeNode.kt @@ -38,28 +38,29 @@ internal class HazeNode( override val shouldAutoInvalidate: Boolean = false override fun ContentDrawScope.draw() { + state.contentDrawing = true log(TAG) { "start draw()" } - if (!useGraphicLayers()) { - // If we're not using graphics layers, just call drawContent and return early - drawContent() - return - } + if (useGraphicLayers()) { + val graphicsContext = currentValueOf(LocalGraphicsContext) - val graphicsContext = currentValueOf(LocalGraphicsContext) + val contentLayer = state.contentLayer + ?.takeUnless { it.isReleased } + ?: graphicsContext.createGraphicsLayer().also { state.contentLayer = it } - val contentLayer = state.contentLayer - ?.takeUnless { it.isReleased } - ?: graphicsContext.createGraphicsLayer().also { state.contentLayer = it } + // First we draw the composable content into a graphics layer + contentLayer.record { + this@draw.drawContent() + } - // First we draw the composable content into a graphics layer - contentLayer.record { - this@draw.drawContent() + // Now we draw `content` into the window canvas + drawLayer(contentLayer) + } else { + // If we're not using graphics layers, just call drawContent and return early + drawContent() } - // Now we draw `content` into the window canvas - drawLayer(contentLayer) - + state.contentDrawing = false log(TAG) { "end draw()" } } diff --git a/haze/src/commonTest/kotlin/dev/chrisbanes/haze/HazeTest.kt b/haze/src/commonTest/kotlin/dev/chrisbanes/haze/HazeTest.kt index 2aa78785..46c8fd26 100644 --- a/haze/src/commonTest/kotlin/dev/chrisbanes/haze/HazeTest.kt +++ b/haze/src/commonTest/kotlin/dev/chrisbanes/haze/HazeTest.kt @@ -3,10 +3,19 @@ package dev.chrisbanes.haze +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.runComposeUiTest +import assertk.assertFailure import assertk.assertThat import assertk.assertions.isFalse import kotlin.test.Test +@OptIn(ExperimentalTestApi::class) class HazeTest { @Test @@ -20,4 +29,18 @@ class HazeTest { assertThat(blockCalled).isFalse() } + + @Test + fun testDescendantModifiers() { + assertFailure { + runComposeUiTest { + setContent { + val hazeState = remember { HazeState() } + Box(Modifier.haze(hazeState)) { + Spacer(Modifier.hazeChild(hazeState, HazeDefaults.style(Color.Blue))) + } + } + } + } + } }