package net.shadowfacts.cacao.view import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.util.NinePatchTexture import net.shadowfacts.cacao.util.RenderHelper import net.shadowfacts.cacao.util.ResettableLazyProperty /** * A helper class for drawing a [NinePatchTexture] in a view. * `NinePatchView` will draw the given nine patch texture filling its bounds. * * @author shadowfacts * @param ninePatch The nine patch texture that this view will draw. */ class NinePatchView(val ninePatch: NinePatchTexture): View() { // Corners protected val `$topLeft` = ResettableLazyProperty { Rect(0.0, 0.0, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble()) } protected val topLeft by `$topLeft` protected val `$topRight` = ResettableLazyProperty { Rect(bounds.width - ninePatch.cornerWidth, 0.0, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble()) } protected val topRight by `$topRight` protected val `$bottomLeft` = ResettableLazyProperty { Rect(0.0, bounds.height - ninePatch.cornerHeight, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble()) } protected val bottomLeft by `$bottomLeft` protected val `$bottomRight` = ResettableLazyProperty { Rect(bounds.width - ninePatch.cornerWidth, bounds.height - ninePatch.cornerHeight, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble()) } protected val bottomRight by `$bottomRight` // Edges protected val `$topMiddle` = ResettableLazyProperty { Rect(ninePatch.cornerWidth.toDouble(), topLeft.top, bounds.width - 2 * ninePatch.cornerWidth, ninePatch.cornerHeight.toDouble()) } protected val topMiddle by `$topMiddle` protected val `$bottomMiddle` = ResettableLazyProperty { Rect(topMiddle.left, bottomLeft.top, topMiddle.width, topMiddle.height) } protected val bottomMiddle by `$bottomMiddle` protected val `$leftMiddle` = ResettableLazyProperty { Rect(topLeft.left, ninePatch.cornerHeight.toDouble(), ninePatch.cornerWidth.toDouble(), bounds.height - 2 * ninePatch.cornerHeight) } protected val leftMiddle by `$leftMiddle` protected val `$rightMiddle` = ResettableLazyProperty { Rect(topRight.left, leftMiddle.top, leftMiddle.width, leftMiddle.height) } protected val rightMiddle by `$rightMiddle` // Center protected val `$center` = ResettableLazyProperty { Rect(topLeft.right, topLeft.bottom, topMiddle.width, leftMiddle.height) } protected val center by `$center` protected val delegates = listOf(`$topLeft`, `$topRight`, `$bottomLeft`, `$bottomRight`, `$topMiddle`, `$bottomMiddle`, `$leftMiddle`, `$rightMiddle`, `$center`) override fun didLayout() { super.didLayout() delegates.forEach(ResettableLazyProperty::reset) } override fun drawContent(mouse: Point, delta: Float) { drawCorners() drawEdges() drawCenter() } private fun drawCorners() { RenderHelper.draw(topLeft, ninePatch.topLeft) RenderHelper.draw(topRight, ninePatch.topRight) RenderHelper.draw(bottomLeft, ninePatch.bottomLeft) RenderHelper.draw(bottomRight, ninePatch.bottomRight) } private fun drawEdges() { // Horizontal for (i in 0 until (topMiddle.width.toInt() / ninePatch.centerWidth)) { RenderHelper.draw(topMiddle.left + i * ninePatch.centerWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, ninePatch.centerWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) RenderHelper.draw(bottomMiddle.left + i * ninePatch.centerWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, ninePatch.centerWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) } val remWidth = topMiddle.width.toInt() % ninePatch.centerWidth if (remWidth > 0) { RenderHelper.draw(topMiddle.right - remWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) RenderHelper.draw(bottomMiddle.right - remWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) } // Vertical for (i in 0 until (leftMiddle.height.toInt() / ninePatch.centerHeight)) { RenderHelper.draw(leftMiddle.left, leftMiddle.top + i * ninePatch.centerHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) RenderHelper.draw(rightMiddle.left, rightMiddle.top + i * ninePatch.centerHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) } val remHeight = leftMiddle.height.toInt() % ninePatch.centerHeight if (remHeight > 0) { RenderHelper.draw(leftMiddle.left, leftMiddle.bottom - remHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) RenderHelper.draw(rightMiddle.left, rightMiddle.bottom - remHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height) } } private fun drawCenter() { for (i in 0 until (center.height.toInt() / ninePatch.centerHeight)) { drawCenterRow(center.top + i * ninePatch.centerHeight.toDouble(), ninePatch.centerHeight.toDouble()) } val remHeight = center.height.toInt() % ninePatch.centerHeight if (remHeight > 0) { drawCenterRow(center.bottom - remHeight, remHeight.toDouble()) } } private fun drawCenterRow(y: Double, height: Double) { for (i in 0 until (center.width.toInt() / ninePatch.centerWidth)) { RenderHelper.draw(center.left + i * ninePatch.centerWidth, y, ninePatch.center.u, ninePatch.center.v, ninePatch.centerWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height) } val remWidth = center.width.toInt() % ninePatch.centerWidth if (remWidth > 0) { RenderHelper.draw(center.right - remWidth, y, ninePatch.center.u, ninePatch.center.v, remWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height) } } }