107 lines
2.8 KiB
Kotlin
107 lines
2.8 KiB
Kotlin
package net.shadowfacts.cacao.view
|
|
|
|
import net.minecraft.client.MinecraftClient
|
|
import net.minecraft.client.font.TextRenderer
|
|
import net.shadowfacts.cacao.geometry.Point
|
|
import net.shadowfacts.cacao.geometry.Size
|
|
import net.shadowfacts.cacao.util.Color
|
|
import net.shadowfacts.cacao.util.RenderHelper
|
|
import kotlin.math.roundToInt
|
|
|
|
/**
|
|
* A simple View that displays text. Allows for controlling the color and shadow of the text. Label cannot be used
|
|
* for multi-line text, instead use [TextView].
|
|
*
|
|
* @author shadowfacts
|
|
* @param text The text of this label.
|
|
* @param shadow Whether the text should be rendered with a shadow or not.
|
|
* @param maxLines The maximum number of lines of text to render.
|
|
* `0` means that there is no line limit and all lines will be rendered.
|
|
* When using a non-zero [maxLines] value, the [intrinsicContentSize] of the Label still assumes all
|
|
* content on one line. So, constraints must be provided to calculate the actual width to use for line
|
|
* wrapping.
|
|
*/
|
|
class Label(
|
|
text: String,
|
|
val shadow: Boolean = true,
|
|
val maxLines: Int = 0,
|
|
val wrappingMode: WrappingMode = WrappingMode.WRAP
|
|
): View() {
|
|
|
|
companion object {
|
|
private val textRenderer: TextRenderer
|
|
get() = MinecraftClient.getInstance().textRenderer
|
|
}
|
|
|
|
enum class WrappingMode {
|
|
WRAP, NO_WRAP
|
|
}
|
|
|
|
/**
|
|
* The text of this label. Mutating this field will update the intrinsic content size and trigger a layout.
|
|
*/
|
|
var text: String = text
|
|
set(value) {
|
|
field = value
|
|
updateIntrinsicContentSize()
|
|
window.layout()
|
|
}
|
|
private lateinit var lines: List<String>
|
|
|
|
var textColor = Color.WHITE
|
|
set(value) {
|
|
field = value
|
|
textColorARGB = value.argb
|
|
}
|
|
private var textColorARGB: Int = textColor.argb
|
|
|
|
private val drawFunc by lazy {
|
|
if (shadow) textRenderer::drawWithShadow else textRenderer::draw
|
|
}
|
|
|
|
override fun wasAdded() {
|
|
super.wasAdded()
|
|
|
|
updateIntrinsicContentSize()
|
|
}
|
|
|
|
private fun updateIntrinsicContentSize() {
|
|
if (RenderHelper.disabled) return
|
|
|
|
val width = textRenderer.getStringWidth(text)
|
|
val height = textRenderer.fontHeight
|
|
intrinsicContentSize = Size(width.toDouble(), height.toDouble())
|
|
}
|
|
|
|
override fun drawContent(mouse: Point, delta: Float) {
|
|
if (!this::lines.isInitialized) {
|
|
computeLines()
|
|
}
|
|
|
|
for (i in 0 until lines.size) {
|
|
val y = i * textRenderer.fontHeight
|
|
drawFunc(lines[i], 0f, y.toFloat(), textColorARGB)
|
|
}
|
|
}
|
|
|
|
override fun didLayout() {
|
|
super.didLayout()
|
|
|
|
computeLines()
|
|
}
|
|
|
|
private fun computeLines() {
|
|
var lines = text.split("\n")
|
|
if (wrappingMode == WrappingMode.WRAP) {
|
|
lines = lines.flatMap {
|
|
val maxWidth = bounds.width.toInt()
|
|
textRenderer.wrapStringToWidthAsList(it, maxWidth)
|
|
}
|
|
}
|
|
if (0 < maxLines && maxLines < lines.size) {
|
|
lines = lines.dropLast(lines.size - maxLines)
|
|
}
|
|
this.lines = lines
|
|
}
|
|
|
|
} |