mirror of
				https://github.com/JakeWharton/mosaic.git
				synced 2025-11-04 06:32:26 +08:00 
			
		
		
		
	Put nodes in charge of rendering themselves
This commit is contained in:
		@ -4,10 +4,13 @@ import androidx.compose.runtime.AbstractApplier
 | 
				
			|||||||
import com.facebook.yoga.YogaMeasureOutput
 | 
					import com.facebook.yoga.YogaMeasureOutput
 | 
				
			||||||
import com.facebook.yoga.YogaNode
 | 
					import com.facebook.yoga.YogaNode
 | 
				
			||||||
import com.facebook.yoga.YogaNodeFactory
 | 
					import com.facebook.yoga.YogaNodeFactory
 | 
				
			||||||
 | 
					import com.jakewharton.crossword.TextCanvas
 | 
				
			||||||
import com.jakewharton.crossword.visualCodePointCount
 | 
					import com.jakewharton.crossword.visualCodePointCount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal sealed class MosaicNode {
 | 
					internal sealed class MosaicNode {
 | 
				
			||||||
	val yoga: YogaNode = YogaNodeFactory.create()
 | 
						val yoga: YogaNode = YogaNodeFactory.create()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						abstract fun render(canvas: TextCanvas)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal class TextNode(initialValue: String = "") : MosaicNode() {
 | 
					internal class TextNode(initialValue: String = "") : MosaicNode() {
 | 
				
			||||||
@ -26,12 +29,30 @@ internal class TextNode(initialValue: String = "") : MosaicNode() {
 | 
				
			|||||||
			yoga.dirty()
 | 
								yoga.dirty()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override fun render(canvas: TextCanvas) {
 | 
				
			||||||
 | 
							value.split('\n').forEachIndexed { index, line ->
 | 
				
			||||||
 | 
								canvas.write(index, 0, line)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	override fun toString() = "Text($value)"
 | 
						override fun toString() = "Text($value)"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal class BoxNode : MosaicNode() {
 | 
					internal class BoxNode : MosaicNode() {
 | 
				
			||||||
	val children = mutableListOf<MosaicNode>()
 | 
						val children = mutableListOf<MosaicNode>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override fun render(canvas: TextCanvas) {
 | 
				
			||||||
 | 
							for (child in children) {
 | 
				
			||||||
 | 
								val childYoga = child.yoga
 | 
				
			||||||
 | 
								val left = childYoga.layoutX.toInt()
 | 
				
			||||||
 | 
								val top = childYoga.layoutY.toInt()
 | 
				
			||||||
 | 
								val right = left + childYoga.layoutWidth.toInt()
 | 
				
			||||||
 | 
								val bottom = top + childYoga.layoutHeight.toInt()
 | 
				
			||||||
 | 
								val clipped = canvas.clip(left, top, right, bottom)
 | 
				
			||||||
 | 
								child.render(clipped)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	override fun toString() = children.joinToString(prefix = "Box(", postfix = ")")
 | 
						override fun toString() = children.joinToString(prefix = "Box(", postfix = ")")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,24 +7,3 @@ internal fun MosaicNode.renderToString(): String {
 | 
				
			|||||||
	render(surface)
 | 
						render(surface)
 | 
				
			||||||
	return surface.toString()
 | 
						return surface.toString()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
private fun MosaicNode.render(canvas: TextCanvas) {
 | 
					 | 
				
			||||||
	when (this) {
 | 
					 | 
				
			||||||
		is TextNode -> {
 | 
					 | 
				
			||||||
			value.split('\n').forEachIndexed { index, line ->
 | 
					 | 
				
			||||||
				canvas.write(index, 0, line)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		is BoxNode -> {
 | 
					 | 
				
			||||||
			for (child in children) {
 | 
					 | 
				
			||||||
				val childYoga = child.yoga
 | 
					 | 
				
			||||||
				val left = childYoga.layoutX.toInt()
 | 
					 | 
				
			||||||
				val top = childYoga.layoutY.toInt()
 | 
					 | 
				
			||||||
				val right = left + childYoga.layoutWidth.toInt()
 | 
					 | 
				
			||||||
				val bottom = top + childYoga.layoutHeight.toInt()
 | 
					 | 
				
			||||||
				val clipped = canvas.clip(left, top, right, bottom)
 | 
					 | 
				
			||||||
				child.render(clipped)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user