Label improvements

Add shadow, line wrapping, line maximum
This commit is contained in:
Shadowfacts 2019-06-27 18:31:06 -04:00
parent cb66900cb5
commit f29e690208
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
3 changed files with 63 additions and 5 deletions

View File

@ -44,6 +44,8 @@ class TestCacaoScreen: CacaoScreen() {
}
})
val label = addView(Label("test ".repeat(100), maxLines = 5))
solver.dsl {
stack.topAnchor equalTo 0
stack.centerXAnchor equalTo this@apply.centerXAnchor
@ -51,9 +53,11 @@ class TestCacaoScreen: CacaoScreen() {
purple.centerXAnchor equalTo blue.centerXAnchor
purple.centerYAnchor equalTo blue.centerYAnchor
// purple.widthAnchor equalTo 50
}
layout()
label.topAnchor equalTo 0
label.leftAnchor equalTo 0
label.widthAnchor equalTo 100
}
// val red = addView(View().apply {

View File

@ -86,7 +86,7 @@ class Window {
* Creates the internal constraints used by the window.
* If overridden, the super-class method must be called.
*/
protected open fun createInternalConstraints() {
protected fun createInternalConstraints() {
solver.dsl {
leftAnchor equalTo 0
topAnchor equalTo 0

View File

@ -6,6 +6,7 @@ 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
@ -13,14 +14,29 @@ import net.shadowfacts.cacao.util.RenderHelper
*
* @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): View() {
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.
*/
@ -28,9 +44,20 @@ class Label(text: String): View() {
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()
@ -47,7 +74,34 @@ class Label(text: String): View() {
}
override fun drawContent(mouse: Point, delta: Float) {
textRenderer.draw(text, 0f, 0f, textColor.argb)
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
}
}