Skip to content

Commit

Permalink
Throw error on descendant layouts (#357)
Browse files Browse the repository at this point in the history
These have never been supported, but it has never been codified...
before this PR.
  • Loading branch information
chrisbanes authored Oct 15, 2024
1 parent 75a45bb commit b90d504
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 15 deletions.
2 changes: 2 additions & 0 deletions haze/src/commonMain/kotlin/dev/chrisbanes/haze/Haze.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class HazeState {
*/
var contentLayer: GraphicsLayer? = null
internal set

internal var contentDrawing = false
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
31 changes: 16 additions & 15 deletions haze/src/commonMain/kotlin/dev/chrisbanes/haze/HazeNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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()" }
}

Expand Down
23 changes: 23 additions & 0 deletions haze/src/commonTest/kotlin/dev/chrisbanes/haze/HazeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)))
}
}
}
}
}
}

0 comments on commit b90d504

Please sign in to comment.