Label improvements
Add shadow, line wrapping, line maximum
This commit is contained in:
parent
cb66900cb5
commit
f29e690208
|
@ -44,6 +44,8 @@ class TestCacaoScreen: CacaoScreen() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
val label = addView(Label("test ".repeat(100), maxLines = 5))
|
||||||
|
|
||||||
solver.dsl {
|
solver.dsl {
|
||||||
stack.topAnchor equalTo 0
|
stack.topAnchor equalTo 0
|
||||||
stack.centerXAnchor equalTo this@apply.centerXAnchor
|
stack.centerXAnchor equalTo this@apply.centerXAnchor
|
||||||
|
@ -51,9 +53,11 @@ class TestCacaoScreen: CacaoScreen() {
|
||||||
purple.centerXAnchor equalTo blue.centerXAnchor
|
purple.centerXAnchor equalTo blue.centerXAnchor
|
||||||
purple.centerYAnchor equalTo blue.centerYAnchor
|
purple.centerYAnchor equalTo blue.centerYAnchor
|
||||||
// purple.widthAnchor equalTo 50
|
// purple.widthAnchor equalTo 50
|
||||||
}
|
|
||||||
|
|
||||||
layout()
|
label.topAnchor equalTo 0
|
||||||
|
label.leftAnchor equalTo 0
|
||||||
|
label.widthAnchor equalTo 100
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// val red = addView(View().apply {
|
// val red = addView(View().apply {
|
||||||
|
|
|
@ -86,7 +86,7 @@ class Window {
|
||||||
* Creates the internal constraints used by the window.
|
* Creates the internal constraints used by the window.
|
||||||
* If overridden, the super-class method must be called.
|
* If overridden, the super-class method must be called.
|
||||||
*/
|
*/
|
||||||
protected open fun createInternalConstraints() {
|
protected fun createInternalConstraints() {
|
||||||
solver.dsl {
|
solver.dsl {
|
||||||
leftAnchor equalTo 0
|
leftAnchor equalTo 0
|
||||||
topAnchor equalTo 0
|
topAnchor equalTo 0
|
||||||
|
|
|
@ -6,6 +6,7 @@ import net.shadowfacts.cacao.geometry.Point
|
||||||
import net.shadowfacts.cacao.geometry.Size
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
import net.shadowfacts.cacao.util.Color
|
import net.shadowfacts.cacao.util.Color
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
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
|
* 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
|
* @author shadowfacts
|
||||||
* @param text The text of this label.
|
* @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 {
|
companion object {
|
||||||
private val textRenderer: TextRenderer
|
private val textRenderer: TextRenderer
|
||||||
get() = MinecraftClient.getInstance().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.
|
* 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) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
updateIntrinsicContentSize()
|
updateIntrinsicContentSize()
|
||||||
|
window.layout()
|
||||||
}
|
}
|
||||||
|
private lateinit var lines: List<String>
|
||||||
|
|
||||||
var textColor = Color.WHITE
|
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() {
|
override fun wasAdded() {
|
||||||
super.wasAdded()
|
super.wasAdded()
|
||||||
|
@ -47,7 +74,34 @@ class Label(text: String): View() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawContent(mouse: Point, delta: Float) {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue