Add ToggleButton
This commit is contained in:
parent
f2d7e0a656
commit
df3523347c
|
@ -13,6 +13,7 @@ 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
|
import net.shadowfacts.cacao.view.button.EnumButton
|
||||||
|
import net.shadowfacts.cacao.view.button.ToggleButton
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -35,9 +36,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(EnumButton(RedstoneMode.HIGH, RedstoneMode.Companion::localize).apply {
|
val purple = blue.addSubview(ToggleButton(false).apply {
|
||||||
handler = {
|
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
|
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
|
// purple.widthAnchor equalTo 50
|
||||||
}
|
}
|
||||||
|
|
||||||
layout()
|
layout()
|
||||||
|
|
|
@ -4,14 +4,15 @@ package net.shadowfacts.cacao.util
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
enum class MouseButton {
|
enum class MouseButton {
|
||||||
LEFT, RIGHT, MIDDLE;
|
LEFT, RIGHT, MIDDLE, UNKNOWN;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromMC(button: Int): MouseButton {
|
fun fromMC(button: Int): MouseButton {
|
||||||
return when (button) {
|
return when (button) {
|
||||||
|
0 -> LEFT
|
||||||
1 -> RIGHT
|
1 -> RIGHT
|
||||||
2 -> MIDDLE
|
2 -> MIDDLE
|
||||||
else -> LEFT
|
else -> UNKNOWN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import net.shadowfacts.cacao.util.Texture
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TextureView(val texture: Texture): View() {
|
class TextureView(var texture: Texture): View() {
|
||||||
|
|
||||||
override fun drawContent(mouse: Point, delta: Float) {
|
override fun drawContent(mouse: Point, delta: Float) {
|
||||||
RenderHelper.draw(bounds, texture)
|
RenderHelper.draw(bounds, texture)
|
||||||
|
|
|
@ -15,7 +15,7 @@ import net.shadowfacts.cacao.view.Label
|
||||||
* @param initialValue The initial enum value for this button.
|
* @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.
|
* @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
|
private val label: Label
|
||||||
get() = content as Label
|
get() = content as Label
|
||||||
|
|
|
@ -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 |
|
@ -5,9 +5,11 @@ import net.shadowfacts.cacao.geometry.Point
|
||||||
import net.shadowfacts.cacao.geometry.Rect
|
import net.shadowfacts.cacao.geometry.Rect
|
||||||
import net.shadowfacts.cacao.util.MouseButton
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
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.BeforeAll
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -34,60 +36,58 @@ class EnumButtonTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCyclesValues() {
|
fun testHandlerCalled() {
|
||||||
val values = mutableListOf<MyEnum>()
|
val called = CompletableFuture<Boolean>()
|
||||||
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)
|
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 = {
|
handler = {
|
||||||
values.add(it.value)
|
called.complete(true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
||||||
assertEquals(1, values.size)
|
assertTrue(called.getNow(false))
|
||||||
assertEquals(MyEnum.TWO, values.last())
|
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)
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
||||||
assertEquals(2, values.size)
|
assertEquals(MyEnum.TWO, button.value)
|
||||||
assertEquals(MyEnum.THREE, values.last())
|
|
||||||
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
||||||
assertEquals(3, values.size)
|
assertEquals(MyEnum.THREE, button.value)
|
||||||
assertEquals(MyEnum.ONE, values.last())
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
||||||
|
assertEquals(MyEnum.ONE, button.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCyclesValuesBackwards() {
|
fun testCyclesValuesBackwards() {
|
||||||
val values = mutableListOf<MyEnum>()
|
val button = window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
|
||||||
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
|
|
||||||
frame = Rect(0.0, 0.0, 25.0, 25.0)
|
frame = Rect(0.0, 0.0, 25.0, 25.0)
|
||||||
content.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)
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
||||||
assertEquals(1, values.size)
|
assertEquals(MyEnum.TWO, button.value)
|
||||||
assertEquals(MyEnum.TWO, values.last())
|
|
||||||
window.mouseClicked(Point(5.0, 5.0), MouseButton.RIGHT)
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.RIGHT)
|
||||||
assertEquals(2, values.size)
|
assertEquals(MyEnum.ONE, button.value)
|
||||||
assertEquals(MyEnum.ONE, values.last())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMiddleClickDoesNotChangeValue() {
|
fun testMiddleClickDoesNotChangeValue() {
|
||||||
val values = mutableListOf<MyEnum>()
|
val button = window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
|
||||||
window.addView(EnumButton(MyEnum.ONE, MyEnum::name).apply {
|
|
||||||
frame = Rect(0.0, 0.0, 25.0, 25.0)
|
frame = Rect(0.0, 0.0, 25.0, 25.0)
|
||||||
content.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)
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.MIDDLE)
|
||||||
assertEquals(1, values.size)
|
assertEquals(MyEnum.ONE, button.value)
|
||||||
assertEquals(MyEnum.ONE, values.last())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue