Add ToggleButton

This commit is contained in:
Shadowfacts 2019-06-23 22:21:59 -04:00
parent f2d7e0a656
commit df3523347c
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
8 changed files with 154 additions and 34 deletions

View File

@ -13,6 +13,7 @@ import net.shadowfacts.cacao.util.Texture
import net.shadowfacts.cacao.view.*
import net.shadowfacts.cacao.view.button.Button
import net.shadowfacts.cacao.view.button.EnumButton
import net.shadowfacts.cacao.view.button.ToggleButton
/**
* @author shadowfacts
@ -35,9 +36,9 @@ class TestCacaoScreen: CacaoScreen() {
intrinsicContentSize = Size(50.0, 50.0)
backgroundColor = Color(0x0000ff)
})
val purple = blue.addSubview(EnumButton(RedstoneMode.HIGH, RedstoneMode.Companion::localize).apply {
val purple = blue.addSubview(ToggleButton(false).apply {
handler = {
println("enum button clicked, new value: ${it.value}")
println("enum button clicked, new value: ${it.state}")
}
})
@ -47,7 +48,7 @@ class TestCacaoScreen: CacaoScreen() {
stack.rightAnchor equalTo 150
purple.centerXAnchor equalTo blue.centerXAnchor
purple.centerYAnchor equalTo blue.centerYAnchor
purple.widthAnchor equalTo 50
// purple.widthAnchor equalTo 50
}
layout()

View File

@ -4,14 +4,15 @@ package net.shadowfacts.cacao.util
* @author shadowfacts
*/
enum class MouseButton {
LEFT, RIGHT, MIDDLE;
LEFT, RIGHT, MIDDLE, UNKNOWN;
companion object {
fun fromMC(button: Int): MouseButton {
return when (button) {
0 -> LEFT
1 -> RIGHT
2 -> MIDDLE
else -> LEFT
else -> UNKNOWN
}
}
}

View File

@ -10,7 +10,7 @@ import net.shadowfacts.cacao.util.Texture
*
* @author shadowfacts
*/
class TextureView(val texture: Texture): View() {
class TextureView(var texture: Texture): View() {
override fun drawContent(mouse: Point, delta: Float) {
RenderHelper.draw(bounds, texture)

View File

@ -15,7 +15,7 @@ import net.shadowfacts.cacao.view.Label
* @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) {
class EnumButton<E: Enum<E>>(initialValue: E, val localizer: (E) -> String): AbstractButton<EnumButton<E>>(Label(localizer(initialValue))) {
private val label: Label
get() = content as Label

View File

@ -0,0 +1,46 @@
package net.shadowfacts.cacao.view.button
import net.minecraft.util.Identifier
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Size
import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.Texture
import net.shadowfacts.cacao.view.TextureView
/**
* A button for toggling between on/off states.
*
* @author shadowfacts
* @param initialState Whether the button starts as on or off.
*/
class ToggleButton(initialState: Boolean): AbstractButton<ToggleButton>(TextureView(if (initialState) ON else OFF).apply {
intrinsicContentSize = Size(19.0, 19.0)
}, padding = 0.0) {
companion object {
val ON = Texture(Identifier("asmr", "textures/gui/toggle.png"), 0, 0)
val OFF = Texture(Identifier("asmr", "textures/gui/toggle.png"), 0, 19)
}
private val textureView: TextureView
get() = content as TextureView
/**
* The button's current on/off state.
* Updating this property updates the button's texture.
*/
var state: Boolean = initialState
set(value) {
field = value
textureView.texture = if (value) ON else OFF
}
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
if (!disabled && (mouseButton == MouseButton.LEFT || mouseButton == MouseButton.RIGHT)) {
state = !state
}
super.mouseClicked(point, mouseButton)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -5,9 +5,11 @@ import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.MouseButton
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.util.concurrent.CompletableFuture
/**
* @author shadowfacts
@ -34,60 +36,58 @@ class EnumButtonTests {
}
@Test
fun testCyclesValues() {
val values = mutableListOf<MyEnum>()
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
fun testHandlerCalled() {
val called = CompletableFuture<Boolean>()
val button = 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)
content.frame = bounds
handler = {
values.add(it.value)
called.complete(true)
}
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(1, values.size)
assertEquals(MyEnum.TWO, values.last())
assertTrue(called.getNow(false))
assertEquals(MyEnum.TWO, button.value)
}
@Test
fun testCyclesValues() {
val button = window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = bounds
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(2, values.size)
assertEquals(MyEnum.THREE, values.last())
assertEquals(MyEnum.TWO, button.value)
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(3, values.size)
assertEquals(MyEnum.ONE, values.last())
assertEquals(MyEnum.THREE, button.value)
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertEquals(MyEnum.ONE, button.value)
}
@Test
fun testCyclesValuesBackwards() {
val values = mutableListOf<MyEnum>()
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
val button = 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())
assertEquals(MyEnum.TWO, button.value)
window.mouseClicked(Point(5.0, 5.0), MouseButton.RIGHT)
assertEquals(2, values.size)
assertEquals(MyEnum.ONE, values.last())
assertEquals(MyEnum.ONE, button.value)
}
@Test
fun testMiddleClickDoesNotChangeValue() {
val values = mutableListOf<MyEnum>()
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
val button = 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())
assertEquals(MyEnum.ONE, button.value)
}
}

View File

@ -0,0 +1,72 @@
package net.shadowfacts.cacao.view.button
import net.shadowfacts.cacao.Window
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.MouseButton
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.util.concurrent.CompletableFuture
/**
* @author shadowfacts
*/
class ToggleButtonTests {
companion object {
@BeforeAll
@JvmStatic
fun setupAll() {
System.setProperty("cacao.drawing.disabled", "true")
}
}
lateinit var window: Window
@BeforeEach
fun setup() {
window = Window()
}
@Test
fun testHandlerCalled() {
val called = CompletableFuture<Boolean>()
val button = window.addView(ToggleButton(false).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = bounds
handler = {
called.complete(true)
}
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertTrue(called.getNow(false))
}
@Test
fun testTogglesValues() {
val button = window.addView(ToggleButton(false).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = bounds
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertTrue(button.state)
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
assertFalse(button.state)
}
@Test
fun testMiddleClickDoesNotChangeValue() {
val button = window.addView(ToggleButton(false).apply {
frame = Rect(0.0, 0.0, 25.0, 25.0)
content.frame = bounds
})
window.mouseClicked(Point(5.0, 5.0), MouseButton.MIDDLE)
assertFalse(button.state)
}
}