Introduce a node layer type (#140)

This owns measurement, placement, and drawing, and will be stackable in the future.
This commit is contained in:
Jake Wharton
2023-03-07 23:34:05 -05:00
committed by GitHub
parent b616a8d79a
commit 94acb0e12b

View File

@ -36,29 +36,33 @@ internal fun interface DebugPolicy {
fun MosaicNode.renderDebug(): String
}
internal abstract class MosaicNodeLayer : Placeable(), Measurable {
abstract val x: Int
abstract val y: Int
abstract fun drawTo(canvas: TextCanvas)
}
internal class MosaicNode(
var measurePolicy: MeasurePolicy,
var drawPolicy: DrawPolicy?,
var staticDrawPolicy: StaticDrawPolicy,
var debugPolicy: DebugPolicy,
) : Placeable(), Measurable {
) : Measurable {
val children = mutableListOf<MosaicNode>()
private val layer: MosaicNodeLayer = object : MosaicNodeLayer() {
private var measureResult: MeasureResult = NotMeasured
override val width get() = measureResult.width
override val height get() = measureResult.height
/** Measure this node (and any children) and update [width] and [height]. */
override fun measure(): Placeable = apply {
override fun measure() = apply {
measureResult = measurePolicy.run { MeasureScope.run { measure(children) } }
}
// These two values are set by a call to `placeAt`.
/** Pixels right relative to parent at which this node will draw. */
var x = 0
override var x = 0
private set
/** Pixels down relative to parent at which this node will draw. */
var y = 0
override var y = 0
private set
override fun placeAt(x: Int, y: Int) {
@ -67,7 +71,7 @@ internal class MosaicNode(
measureResult.placeChildren()
}
private fun drawTo(canvas: TextCanvas) {
override fun drawTo(canvas: TextCanvas) {
val drawPolicy = drawPolicy
if (drawPolicy != null) {
drawPolicy.performDraw(canvas)
@ -78,17 +82,25 @@ internal class MosaicNode(
val top = child.y
val right = left + child.width - 1
val bottom = top + child.height - 1
child.drawTo(canvas[top..bottom, left..right])
child.layer.drawTo(canvas[top..bottom, left..right])
}
}
}
}
}
override fun measure(): Placeable = layer.measure()
val width: Int get() = layer.width
val height: Int get() = layer.height
val x: Int get() = layer.x
val y: Int get() = layer.y
fun draw(): TextCanvas {
val placeable = measure()
placeable.place(0, 0)
val surface = TextSurface(placeable.width, placeable.height)
drawTo(surface)
layer.drawTo(surface)
return surface
}