Add EnumButton

This commit is contained in:
Shadowfacts 2019-06-23 21:55:42 -04:00
parent b48b72d5bb
commit 204731e03c
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
7 changed files with 165 additions and 7 deletions

View File

@ -1,6 +1,7 @@
package net.shadowfacts.asmr package net.shadowfacts.asmr
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.shadowfacts.asmr.util.RedstoneMode
import net.shadowfacts.kiwidsl.dsl import net.shadowfacts.kiwidsl.dsl
import net.shadowfacts.cacao.CacaoScreen import net.shadowfacts.cacao.CacaoScreen
import net.shadowfacts.cacao.Window import net.shadowfacts.cacao.Window
@ -11,6 +12,7 @@ import net.shadowfacts.cacao.util.NinePatchTexture
import net.shadowfacts.cacao.util.Texture import net.shadowfacts.cacao.util.Texture
import net.shadowfacts.cacao.view.* import net.shadowfacts.cacao.view.*
import net.shadowfacts.cacao.view.button.Button import net.shadowfacts.cacao.view.button.Button
import net.shadowfacts.cacao.view.button.EnumButton
/** /**
* @author shadowfacts * @author shadowfacts
@ -33,11 +35,9 @@ class TestCacaoScreen: CacaoScreen() {
intrinsicContentSize = Size(50.0, 50.0) intrinsicContentSize = Size(50.0, 50.0)
backgroundColor = Color(0x0000ff) backgroundColor = Color(0x0000ff)
}) })
val purple = blue.addSubview(Button(Label("Hello, button!").apply { val purple = blue.addSubview(EnumButton(RedstoneMode.HIGH, RedstoneMode.Companion::localize).apply {
textColor = Color.WHITE
}).apply {
handler = { handler = {
println("$it clicked!") println("enum button clicked, new value: ${it.value}")
} }
}) })
@ -47,6 +47,7 @@ class TestCacaoScreen: CacaoScreen() {
stack.rightAnchor equalTo 150 stack.rightAnchor equalTo 150
purple.centerXAnchor equalTo blue.centerXAnchor purple.centerXAnchor equalTo blue.centerXAnchor
purple.centerYAnchor equalTo blue.centerYAnchor purple.centerYAnchor equalTo blue.centerYAnchor
purple.widthAnchor equalTo 50
} }
layout() layout()

View File

@ -0,0 +1,14 @@
package net.shadowfacts.asmr.util
/**
* @author shadowfacts
*/
enum class RedstoneMode {
HIGH, LOW, TOGGLE;
companion object {
fun localize(value: RedstoneMode): String {
return value.name.toLowerCase().capitalize()
}
}
}

View File

@ -15,7 +15,7 @@ import net.shadowfacts.cacao.geometry.Rect
*/ */
object RenderHelper { object RenderHelper {
private val disabled = (System.getProperty("cacao.drawing.disabled") ?: "false").toBoolean() val disabled = (System.getProperty("cacao.drawing.disabled") ?: "false").toBoolean()
// TODO: find a better place for this // TODO: find a better place for this
fun playSound(event: SoundEvent) { fun playSound(event: SoundEvent) {

View File

@ -5,6 +5,7 @@ import net.minecraft.client.font.TextRenderer
import net.shadowfacts.cacao.geometry.Point 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
/** /**
* 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
@ -29,7 +30,7 @@ class Label(text: String): View() {
updateIntrinsicContentSize() updateIntrinsicContentSize()
} }
var textColor = Color(0x404040) var textColor = Color.WHITE
override fun wasAdded() { override fun wasAdded() {
super.wasAdded() super.wasAdded()
@ -38,6 +39,8 @@ class Label(text: String): View() {
} }
private fun updateIntrinsicContentSize() { private fun updateIntrinsicContentSize() {
if (RenderHelper.disabled) return
val width = textRenderer.getStringWidth(text) val width = textRenderer.getStringWidth(text)
val height = textRenderer.fontHeight val height = textRenderer.fontHeight
intrinsicContentSize = Size(width.toDouble(), height.toDouble()) intrinsicContentSize = Size(width.toDouble(), height.toDouble())

View File

@ -126,7 +126,7 @@ abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
handler(this as Impl) handler(this as Impl)
if (clickSoundEnabled) { if (clickSoundEnabled && !RenderHelper.disabled) {
RenderHelper.playSound(SoundEvents.UI_BUTTON_CLICK) RenderHelper.playSound(SoundEvents.UI_BUTTON_CLICK)
} }
} }

View File

@ -0,0 +1,45 @@
package net.shadowfacts.cacao.view.button
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.EnumHelper
import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.view.Label
/**
* A button that cycles through enum values.
* Left click: forwards
* Right click: backwards
* All other mouse buttons call the handler with the unchanged value
*
* @author shadowfacts
* @param initialValue The initial enum value for this button.
* @param localizer A function that takes an enum value and converts into a string for the button's label.
*/
class EnumButton<E: Enum<E>>(initialValue: E, val localizer: (E) -> String, padding: Double = 4.0): AbstractButton<EnumButton<E>>(Label(localizer(initialValue)), padding) {
private val label: Label
get() = content as Label
/**
* The current value of the enum button.
* Updating this property will use the [localizer] to update the label.
*/
var value: E = initialValue
set(value) {
field = value
label.text = localizer(value)
}
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
if (!disabled) {
value = when (mouseButton) {
MouseButton.LEFT -> EnumHelper.next(value)
MouseButton.RIGHT -> EnumHelper.previous(value)
else -> value
}
}
super.mouseClicked(point, mouseButton)
}
}

View File

@ -0,0 +1,95 @@
package net.shadowfacts.cacao.view
import net.shadowfacts.cacao.Window
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.view.button.EnumButton
import net.shadowfacts.kiwidsl.dsl
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
/**
* @author shadowfacts
*/
class EnumButtonTests {
companion object {
@BeforeAll
@JvmStatic
fun setupAll() {
System.setProperty("cacao.drawing.disabled", "true")
}
}
enum class MyEnum {
ONE, TWO, THREE
}
lateinit var window: Window
@BeforeEach
fun setup() {
window = Window()
}
@Test
fun testCyclesValues() {
val values = mutableListOf<MyEnum>()
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = Rect(0.0, 0.0, 25.0, 25.0)
handler = {
values.add(it.value)
}
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(1, values.size)
assertEquals(MyEnum.TWO, values.last())
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(2, values.size)
assertEquals(MyEnum.THREE, values.last())
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(3, values.size)
assertEquals(MyEnum.ONE, values.last())
}
@Test
fun testCyclesValuesBackwards() {
val values = mutableListOf<MyEnum>()
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = Rect(0.0, 0.0, 25.0, 25.0)
handler = {
values.add(it.value)
}
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(1, values.size)
assertEquals(MyEnum.TWO, values.last())
window.mouseClicked(Point(5.0, 5.0), MouseButton.RIGHT)
assertEquals(2, values.size)
assertEquals(MyEnum.ONE, values.last())
}
@Test
fun testMiddleClickDoesNotChangeValue() {
val values = mutableListOf<MyEnum>()
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = Rect(0.0, 0.0, 25.0, 25.0)
handler = {
values.add(it.value)
}
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.MIDDLE)
assertEquals(1, values.size)
assertEquals(MyEnum.ONE, values.last())
}
}