Compare commits
4 Commits
bee2eceb10
...
f474c4c8bf
Author | SHA1 | Date |
---|---|---|
Shadowfacts | f474c4c8bf | |
Shadowfacts | 6485fd1035 | |
Shadowfacts | 62fbc10aa3 | |
Shadowfacts | bf7e7bd24c |
|
@ -1,4 +1,5 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
logs/
|
||||||
|
|
||||||
# gradle
|
# gradle
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
package net.shadowfacts.asmr
|
package net.shadowfacts.asmr
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.kiwidsl.dsl
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
import net.shadowfacts.cacao.CacaoScreen
|
import net.shadowfacts.cacao.CacaoScreen
|
||||||
import net.shadowfacts.cacao.view.View
|
|
||||||
import net.shadowfacts.cacao.Window
|
import net.shadowfacts.cacao.Window
|
||||||
import net.shadowfacts.cacao.geometry.Axis
|
import net.shadowfacts.cacao.geometry.Axis
|
||||||
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.MouseButton
|
import net.shadowfacts.cacao.util.NinePatchTexture
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
import net.shadowfacts.cacao.util.Texture
|
||||||
import net.shadowfacts.cacao.view.StackView
|
import net.shadowfacts.cacao.view.*
|
||||||
|
import net.shadowfacts.cacao.view.button.Button
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -22,33 +22,24 @@ class TestCacaoScreen: CacaoScreen() {
|
||||||
val stack = addView(StackView(Axis.VERTICAL, StackView.Distribution.CENTER).apply {
|
val stack = addView(StackView(Axis.VERTICAL, StackView.Distribution.CENTER).apply {
|
||||||
backgroundColor = Color.WHITE
|
backgroundColor = Color.WHITE
|
||||||
})
|
})
|
||||||
val red = stack.addArrangedSubview(View().apply {
|
val red = stack.addArrangedSubview(TextureView(Texture(Identifier("textures/block/birch_log_top.png"), 0, 0, 16, 16)).apply {
|
||||||
intrinsicContentSize = Size(50.0, 50.0)
|
intrinsicContentSize = Size(50.0, 50.0)
|
||||||
backgroundColor = Color(0xff0000)
|
|
||||||
})
|
})
|
||||||
val green = stack.addArrangedSubview(View().apply {
|
val buttonNinePatch = NinePatchTexture(Texture(Identifier("textures/gui/widgets.png"), 0, 66), 3, 3, 194, 14)
|
||||||
|
val green = stack.addArrangedSubview(NinePatchView(buttonNinePatch).apply {
|
||||||
intrinsicContentSize = Size(75.0, 100.0)
|
intrinsicContentSize = Size(75.0, 100.0)
|
||||||
backgroundColor = Color(0x00ff00)
|
|
||||||
})
|
})
|
||||||
val blue = stack.addArrangedSubview(View().apply {
|
val blue = stack.addArrangedSubview(View().apply {
|
||||||
intrinsicContentSize = Size(50.0, 50.0)
|
intrinsicContentSize = Size(50.0, 50.0)
|
||||||
backgroundColor = Color(0x0000ff)
|
backgroundColor = Color(0x0000ff)
|
||||||
})
|
})
|
||||||
val purple = blue.addSubview(object: View() {
|
val purple = blue.addSubview(Button(Label("Hello, button!").apply {
|
||||||
init {
|
textColor = Color.WHITE
|
||||||
intrinsicContentSize = Size(25.0, 25.0)
|
}).apply {
|
||||||
backgroundColor = Color(0x800080)
|
handler = {
|
||||||
}
|
println("$it clicked!")
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
|
||||||
println("hello world")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawContent(mouse: Point, delta: Float) {
|
|
||||||
if (mouse in bounds) {
|
|
||||||
RenderHelper.fill(bounds, Color.WHITE)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
background = NinePatchView(buttonNinePatch)
|
||||||
})
|
})
|
||||||
|
|
||||||
solver.dsl {
|
solver.dsl {
|
||||||
|
|
|
@ -35,6 +35,8 @@ open class CacaoScreen: Screen(TextComponent("CacaoScreen")) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(mouseX: Int, mouseY: Int, delta: Float) {
|
override fun render(mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
renderBackground()
|
||||||
|
|
||||||
val mouse = Point(mouseX, mouseY)
|
val mouse = Point(mouseX, mouseY)
|
||||||
windows.forEach {
|
windows.forEach {
|
||||||
it.draw(mouse, delta)
|
it.draw(mouse, delta)
|
||||||
|
|
|
@ -9,4 +9,8 @@ data class Point(val x: Double, val y: Double) {
|
||||||
|
|
||||||
constructor(x: Int, y: Int): this(x.toDouble(), y.toDouble())
|
constructor(x: Int, y: Int): this(x.toDouble(), y.toDouble())
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val ORIGIN = Point(0.0, 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package net.shadowfacts.cacao.util
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
data class NinePatchTexture(val texture: Texture, val cornerWidth: Int, val cornerHeight: Int, val centerWidth: Int, val centerHeight: Int) {
|
||||||
|
|
||||||
|
// Corners
|
||||||
|
val topLeft by lazy {
|
||||||
|
texture
|
||||||
|
}
|
||||||
|
val topRight by lazy {
|
||||||
|
Texture(texture.location, texture.u + cornerWidth + centerWidth, texture.v, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
val bottomLeft by lazy {
|
||||||
|
Texture(texture.location, texture.u, texture.v + cornerHeight + centerHeight, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
val bottomRight by lazy {
|
||||||
|
Texture(texture.location, topRight.u, bottomLeft.v, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edges
|
||||||
|
val topMiddle by lazy {
|
||||||
|
Texture(texture.location, texture.u + cornerWidth, texture.v, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
val bottomMiddle by lazy {
|
||||||
|
Texture(texture.location, topMiddle.u, bottomLeft.v, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
val leftMiddle by lazy {
|
||||||
|
Texture(texture.location, texture.u, texture.v + cornerHeight, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
val rightMiddle by lazy {
|
||||||
|
Texture(texture.location, topRight.u, leftMiddle.v, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center
|
||||||
|
val center by lazy {
|
||||||
|
Texture(texture.location, texture.u + cornerWidth, texture.v + cornerHeight, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package net.shadowfacts.cacao.util
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ObservableLateInitProperty<T: Any>(val observer: (T) -> Unit) {
|
||||||
|
|
||||||
|
lateinit var storage: T
|
||||||
|
|
||||||
|
operator fun getValue(thisRef: Any, property: KProperty<*>): T {
|
||||||
|
return storage
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
|
||||||
|
storage = value
|
||||||
|
observer(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package net.shadowfacts.cacao.util
|
package net.shadowfacts.cacao.util
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager
|
import com.mojang.blaze3d.platform.GlStateManager
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.client.gui.DrawableHelper
|
import net.minecraft.client.gui.DrawableHelper
|
||||||
import net.shadowfacts.cacao.geometry.Rect
|
import net.shadowfacts.cacao.geometry.Rect
|
||||||
|
|
||||||
|
@ -22,6 +23,24 @@ object RenderHelper {
|
||||||
DrawableHelper.fill(rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt(), color.argb)
|
DrawableHelper.fill(rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt(), color.argb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds and draws the given [texture] filling the [rect].
|
||||||
|
*/
|
||||||
|
fun draw(rect: Rect, texture: Texture) {
|
||||||
|
if (disabled) return
|
||||||
|
color(1f, 1f, 1f, 1f)
|
||||||
|
MinecraftClient.getInstance().textureManager.bindTexture(texture.location)
|
||||||
|
draw(rect.left, rect.top, texture.u, texture.v, rect.width, rect.height, texture.width, texture.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the bound texture with the given screen and texture position and size.
|
||||||
|
*/
|
||||||
|
fun draw(x: Double, y: Double, u: Int, v: Int, width: Double, height: Double, textureWidth: Int, textureHeight: Int) {
|
||||||
|
if (disabled) return
|
||||||
|
DrawableHelper.blit(x.toInt(), y.toInt(), u.toFloat(), v.toFloat(), width.toInt(), height.toInt(), textureWidth, textureHeight)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.lwjgl.opengl.GL11.glPushMatrix
|
* @see org.lwjgl.opengl.GL11.glPushMatrix
|
||||||
*/
|
*/
|
||||||
|
@ -46,4 +65,9 @@ object RenderHelper {
|
||||||
GlStateManager.translated(x, y, z)
|
GlStateManager.translated(x, y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun color(r: Float, g: Float, b: Float, alpha: Float) {
|
||||||
|
if (disabled) return
|
||||||
|
GlStateManager.color4f(r, g, b, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package net.shadowfacts.cacao.util
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class that represents a texture.
|
||||||
|
*
|
||||||
|
* @author shadowfacts
|
||||||
|
* @param location The identifier representing the resource-pack location of the texture image.
|
||||||
|
* @param u The X coordinate in pixels of where the texture starts within the image.
|
||||||
|
* @param v The Y coordinate in pixels of where the texture starts within the image.
|
||||||
|
* @param width The width in pixels of the entire image.
|
||||||
|
* @param height The height in pixels of the entire image.
|
||||||
|
*/
|
||||||
|
data class Texture(val location: Identifier, val u: Int, val v: Int, val width: Int = 256, val height: Int = 256)
|
|
@ -0,0 +1,103 @@
|
||||||
|
package net.shadowfacts.cacao.view
|
||||||
|
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.geometry.Rect
|
||||||
|
import net.shadowfacts.cacao.util.NinePatchTexture
|
||||||
|
import net.shadowfacts.cacao.util.RenderHelper
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
|
|
||||||
|
// Corners
|
||||||
|
private val topLeft: Rect by lazy {
|
||||||
|
Rect(0.0, 0.0, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
||||||
|
}
|
||||||
|
private val topRight by lazy {
|
||||||
|
Rect(bounds.width - ninePatch.cornerWidth, 0.0, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
||||||
|
}
|
||||||
|
private val bottomLeft by lazy {
|
||||||
|
Rect(0.0, bounds.height - ninePatch.cornerHeight, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
||||||
|
}
|
||||||
|
private val bottomRight by lazy {
|
||||||
|
Rect(bounds.width - ninePatch.cornerWidth, bounds.height - ninePatch.cornerHeight, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edges
|
||||||
|
private val topMiddle by lazy {
|
||||||
|
Rect(ninePatch.cornerWidth.toDouble(), topLeft.top, bounds.width - 2 * ninePatch.cornerWidth, ninePatch.cornerHeight.toDouble())
|
||||||
|
}
|
||||||
|
private val bottomMiddle by lazy {
|
||||||
|
Rect(topMiddle.left, bottomLeft.top, topMiddle.width, topMiddle.height)
|
||||||
|
}
|
||||||
|
private val leftMiddle by lazy {
|
||||||
|
Rect(topLeft.left, ninePatch.cornerHeight.toDouble(), ninePatch.cornerWidth.toDouble(), bounds.height - 2 * ninePatch.cornerHeight)
|
||||||
|
}
|
||||||
|
private val rightMiddle by lazy {
|
||||||
|
Rect(topRight.left, leftMiddle.top, leftMiddle.width, leftMiddle.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center
|
||||||
|
private val center by lazy {
|
||||||
|
Rect(topLeft.right, topLeft.bottom, topMiddle.width, leftMiddle.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawContent(mouse: Point, delta: Float) {
|
||||||
|
drawCorners()
|
||||||
|
drawEdges()
|
||||||
|
drawCenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawCorners() {
|
||||||
|
RenderHelper.draw(topLeft, ninePatch.topLeft)
|
||||||
|
RenderHelper.draw(topRight, ninePatch.topRight)
|
||||||
|
RenderHelper.draw(bottomLeft, ninePatch.bottomLeft)
|
||||||
|
RenderHelper.draw(bottomRight, ninePatch.bottomRight)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawEdges() {
|
||||||
|
// Horizontal
|
||||||
|
for (i in 0 until (topMiddle.width.toInt() / ninePatch.centerWidth)) {
|
||||||
|
RenderHelper.draw(topMiddle.left + i * ninePatch.centerWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, ninePatch.centerWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
RenderHelper.draw(bottomMiddle.left + i * ninePatch.centerWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, ninePatch.centerWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
}
|
||||||
|
val remWidth = topMiddle.width.toInt() % ninePatch.centerWidth
|
||||||
|
if (remWidth > 0) {
|
||||||
|
RenderHelper.draw(topMiddle.right - remWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
RenderHelper.draw(bottomMiddle.right - remWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical
|
||||||
|
for (i in 0 until (leftMiddle.height.toInt() / ninePatch.centerHeight)) {
|
||||||
|
RenderHelper.draw(leftMiddle.left, leftMiddle.top + i * ninePatch.centerHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
RenderHelper.draw(rightMiddle.left, rightMiddle.top + i * ninePatch.centerHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
}
|
||||||
|
val remHeight = leftMiddle.height.toInt() % ninePatch.centerHeight
|
||||||
|
if (remHeight > 0) {
|
||||||
|
RenderHelper.draw(leftMiddle.left, leftMiddle.bottom - remHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
RenderHelper.draw(rightMiddle.left, rightMiddle.bottom - remHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawCenter() {
|
||||||
|
for (i in 0 until (center.height.toInt() / ninePatch.centerHeight)) {
|
||||||
|
drawCenterRow(center.top + i * ninePatch.centerHeight.toDouble(), ninePatch.centerHeight.toDouble())
|
||||||
|
}
|
||||||
|
val remHeight = center.height.toInt() % ninePatch.centerHeight
|
||||||
|
if (remHeight > 0) {
|
||||||
|
drawCenterRow(center.bottom - remHeight, remHeight.toDouble())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawCenterRow(y: Double, height: Double) {
|
||||||
|
for (i in 0 until (center.width.toInt() / ninePatch.centerWidth)) {
|
||||||
|
RenderHelper.draw(center.left + i * ninePatch.centerWidth, y, ninePatch.center.u, ninePatch.center.v, ninePatch.centerWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
}
|
||||||
|
val remWidth = center.width.toInt() % ninePatch.centerWidth
|
||||||
|
if (remWidth > 0) {
|
||||||
|
RenderHelper.draw(center.right - remWidth, y, ninePatch.center.u, ninePatch.center.v, remWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package net.shadowfacts.cacao.view
|
||||||
|
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.util.RenderHelper
|
||||||
|
import net.shadowfacts.cacao.util.Texture
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class for drawing a [Texture] in a view.
|
||||||
|
* `TextureView` will draw the given texture filling the bounds of the view.
|
||||||
|
*
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class TextureView(val texture: Texture): View() {
|
||||||
|
|
||||||
|
override fun drawContent(mouse: Point, delta: Float) {
|
||||||
|
RenderHelper.draw(bounds, texture)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,9 @@
|
||||||
package net.shadowfacts.cacao.view
|
package net.shadowfacts.cacao.view
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager
|
|
||||||
import net.shadowfacts.kiwidsl.dsl
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
import net.shadowfacts.cacao.LayoutVariable
|
import net.shadowfacts.cacao.LayoutVariable
|
||||||
import net.shadowfacts.cacao.geometry.*
|
import net.shadowfacts.cacao.geometry.*
|
||||||
import net.shadowfacts.cacao.util.Color
|
import net.shadowfacts.cacao.util.*
|
||||||
import net.shadowfacts.cacao.util.LowestCommonAncestor
|
|
||||||
import net.shadowfacts.cacao.util.MouseButton
|
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
|
||||||
import no.birkett.kiwi.Constraint
|
import no.birkett.kiwi.Constraint
|
||||||
import no.birkett.kiwi.Solver
|
import no.birkett.kiwi.Solver
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -18,7 +14,7 @@ import java.util.*
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
open class View {
|
open class View() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constraint solver used by the [net.shadowfacts.cacao.Window] this view belongs to.
|
* The constraint solver used by the [net.shadowfacts.cacao.Window] this view belongs to.
|
||||||
|
@ -60,13 +56,25 @@ open class View {
|
||||||
val centerYAnchor = LayoutVariable(this, "centerY")
|
val centerYAnchor = LayoutVariable(this, "centerY")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The rectangle for this view in the coordinate system of its superview view (or the window, if there is no superview).
|
* Whether this view uses constraint-based layout.
|
||||||
* Not initialized until [didLayout] called.
|
* If `false`, the view's `frame` must be set manually and the layout anchors may not be used.
|
||||||
|
* Note: some views (such as [StackView] require arranged subviews to use constraint based layout.
|
||||||
|
*
|
||||||
|
* Default is `true`.
|
||||||
*/
|
*/
|
||||||
lateinit var frame: Rect
|
var usesConstraintBasedLayout = true
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rectangle for this view in the coordinate system of its superview view (or the window, if there is no superview).
|
||||||
|
* If using constraint based layout, this property is not initialized until [didLayout] called.
|
||||||
|
* Otherwise, this must be set manually.
|
||||||
|
* Setting this property updates the [bounds].
|
||||||
|
*/
|
||||||
|
var frame: Rect by ObservableLateInitProperty { this.bounds = Rect(Point.ORIGIN, it.size) }
|
||||||
/**
|
/**
|
||||||
* The rectangle for this view in its own coordinate system.
|
* The rectangle for this view in its own coordinate system.
|
||||||
* Not initialized until [didLayout] called.
|
* If using constraint based layout, this property is not initialized until [didLayout] called.
|
||||||
|
* Otherwise, this will be initialized when [frame] is set.
|
||||||
*/
|
*/
|
||||||
lateinit var bounds: Rect
|
lateinit var bounds: Rect
|
||||||
|
|
||||||
|
@ -102,6 +110,11 @@ open class View {
|
||||||
*/
|
*/
|
||||||
val subviews: List<View> = _subviews
|
val subviews: List<View> = _subviews
|
||||||
|
|
||||||
|
constructor(frame: Rect): this() {
|
||||||
|
this.usesConstraintBasedLayout = false
|
||||||
|
this.frame = frame
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for retrieve the anchor for a specific position on the given axis.
|
* Helper method for retrieve the anchor for a specific position on the given axis.
|
||||||
*/
|
*/
|
||||||
|
@ -163,6 +176,8 @@ open class View {
|
||||||
* If overridden, the super-class method must be called.
|
* If overridden, the super-class method must be called.
|
||||||
*/
|
*/
|
||||||
open fun createInternalConstraints() {
|
open fun createInternalConstraints() {
|
||||||
|
if (!usesConstraintBasedLayout) return
|
||||||
|
|
||||||
solver.dsl {
|
solver.dsl {
|
||||||
rightAnchor equalTo (leftAnchor + widthAnchor)
|
rightAnchor equalTo (leftAnchor + widthAnchor)
|
||||||
bottomAnchor equalTo (topAnchor + heightAnchor)
|
bottomAnchor equalTo (topAnchor + heightAnchor)
|
||||||
|
@ -172,7 +187,7 @@ open class View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateIntrinsicContentSizeConstraints(old: Size?, new: Size?) {
|
private fun updateIntrinsicContentSizeConstraints(old: Size?, new: Size?) {
|
||||||
if (!this::solver.isInitialized) return
|
if (!usesConstraintBasedLayout || !this::solver.isInitialized) return
|
||||||
|
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
solver.removeConstraint(intrinsicContentSizeWidthConstraint!!)
|
solver.removeConstraint(intrinsicContentSizeWidthConstraint!!)
|
||||||
|
@ -193,23 +208,26 @@ open class View {
|
||||||
open fun didLayout() {
|
open fun didLayout() {
|
||||||
subviews.forEach(View::didLayout)
|
subviews.forEach(View::didLayout)
|
||||||
|
|
||||||
|
if (usesConstraintBasedLayout) {
|
||||||
val superviewLeft = superview?.leftAnchor?.value ?: 0.0
|
val superviewLeft = superview?.leftAnchor?.value ?: 0.0
|
||||||
val superviewTop = superview?.topAnchor?.value ?: 0.0
|
val superviewTop = superview?.topAnchor?.value ?: 0.0
|
||||||
frame = Rect(leftAnchor.value - superviewLeft, topAnchor.value - superviewTop, widthAnchor.value, heightAnchor.value)
|
frame = Rect(leftAnchor.value - superviewLeft, topAnchor.value - superviewTop, widthAnchor.value, heightAnchor.value)
|
||||||
bounds = Rect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
|
bounds = Rect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to draw this view.
|
* Called to draw this view.
|
||||||
* This method should not be called directly, it is called by the parent view/window.
|
* This method should not be called directly, it is called by the parent view/window.
|
||||||
* This method may not be overridden, use [drawContent] to draw any custom content.
|
* This method generally should not be overridden, but it is left open for internal framework use.
|
||||||
|
* Use [drawContent] to draw any custom content.
|
||||||
*
|
*
|
||||||
* @param mouse The position of the mouse in the coordinate system of this view.
|
* @param mouse The position of the mouse in the coordinate system of this view.
|
||||||
* @param delta The time since the last frame.
|
* @param delta The time since the last frame.
|
||||||
*/
|
*/
|
||||||
fun draw(mouse: Point, delta: Float) {
|
open fun draw(mouse: Point, delta: Float) {
|
||||||
RenderHelper.pushMatrix()
|
RenderHelper.pushMatrix()
|
||||||
RenderHelper.translate(frame.left, frame.top, 0.0)
|
RenderHelper.translate(frame.left, frame.top)
|
||||||
|
|
||||||
RenderHelper.fill(bounds, backgroundColor)
|
RenderHelper.fill(bounds, backgroundColor)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package net.shadowfacts.cacao.view.button
|
||||||
|
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
|
import net.shadowfacts.cacao.util.RenderHelper
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A abstract button class. Cannot be constructed directly, used for creating button implementations with their own logic.
|
||||||
|
* Use [Button] for a generic no-frills button.
|
||||||
|
*
|
||||||
|
* @author shadowfacts
|
||||||
|
* @param Impl The type of the concrete implementation of the button.
|
||||||
|
* Used to allow the [handler] to receive the exact button type that was constructed.
|
||||||
|
* @param content The [View] that provides the content of this button.
|
||||||
|
* Will be added as a subview of the button and laid out using constraints.
|
||||||
|
* @param padding The padding between the [content] and the edges of the button.
|
||||||
|
*/
|
||||||
|
abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val padding: Double = 4.0): View() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function that handles when this button is clicked.
|
||||||
|
* The parameter is the type of the concrete button implementation that was used.
|
||||||
|
*/
|
||||||
|
var handler: ((Impl) -> Unit)? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the button is disabled.
|
||||||
|
* Disabled buttons have a different background ([disabledBackground]) and do not receive click events.
|
||||||
|
*/
|
||||||
|
var disabled = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The normal background view to draw behind the button content. It will be added as a subview during [wasAdded],
|
||||||
|
* so all background view properties must be specified prior to the button being added to a view hierarchy.
|
||||||
|
*
|
||||||
|
* The background will fill the entire button (going beneath the content [padding]).
|
||||||
|
* There are also [hoveredBackground] and [disabledBackground] for those states.
|
||||||
|
* If a [backgroundColor] is specified, it will be drawn behind the background View and thus not visible
|
||||||
|
* unless the background view is not fully opaque.
|
||||||
|
*/
|
||||||
|
var background: View? = null
|
||||||
|
/**
|
||||||
|
* The background to draw when the button is hovered over by the mouse.
|
||||||
|
* If `null`, the normal [background] will be used.
|
||||||
|
* @see background
|
||||||
|
*/
|
||||||
|
var hoveredBackground: View? = null
|
||||||
|
/**
|
||||||
|
* The background to draw when the button is [disabled].
|
||||||
|
* If `null`, the normal [background] will be used.
|
||||||
|
* @see background
|
||||||
|
*/
|
||||||
|
var disabledBackground: View? = null
|
||||||
|
|
||||||
|
override fun wasAdded() {
|
||||||
|
solver.dsl {
|
||||||
|
addSubview(content)
|
||||||
|
content.leftAnchor equalTo (leftAnchor + padding)
|
||||||
|
content.rightAnchor equalTo (rightAnchor - padding)
|
||||||
|
content.topAnchor equalTo (topAnchor + padding)
|
||||||
|
content.bottomAnchor equalTo (bottomAnchor - padding)
|
||||||
|
|
||||||
|
listOfNotNull(background, hoveredBackground, disabledBackground).forEach {
|
||||||
|
addSubview(it)
|
||||||
|
it.leftAnchor equalTo leftAnchor
|
||||||
|
it.rightAnchor equalTo rightAnchor
|
||||||
|
it.topAnchor equalTo topAnchor
|
||||||
|
it.bottomAnchor equalTo bottomAnchor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.wasAdded()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(mouse: Point, delta: Float) {
|
||||||
|
RenderHelper.pushMatrix()
|
||||||
|
RenderHelper.translate(frame.left, frame.top)
|
||||||
|
|
||||||
|
RenderHelper.fill(bounds, backgroundColor)
|
||||||
|
|
||||||
|
var currentBackground: View? = background
|
||||||
|
if (mouse in bounds) {
|
||||||
|
currentBackground = hoveredBackground ?: currentBackground
|
||||||
|
}
|
||||||
|
if (disabled) {
|
||||||
|
currentBackground = disabledBackground ?: currentBackground
|
||||||
|
}
|
||||||
|
// don't need to convert mouse to background coordinate system
|
||||||
|
// the edges are all pinned, so the coordinate space is the same
|
||||||
|
currentBackground?.draw(mouse, delta)
|
||||||
|
|
||||||
|
val mouseInContent = convert(mouse, to = content)
|
||||||
|
content.draw(mouseInContent, delta)
|
||||||
|
|
||||||
|
// don't draw subviews, otherwise all background views + content will get drawn
|
||||||
|
|
||||||
|
RenderHelper.popMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
||||||
|
if (disabled) return
|
||||||
|
|
||||||
|
val handler = handler
|
||||||
|
if (handler != null) {
|
||||||
|
// We can perform an unchecked cast here because we are certain that Impl will be the concrete implementation
|
||||||
|
// of AbstractButton.
|
||||||
|
// For example, an implementing class may be defined as such: `class Button: AbstractButton<Button>`
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
handler(this as Impl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shadowfacts.cacao.view.button
|
||||||
|
|
||||||
|
import net.shadowfacts.cacao.view.View
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple button implementation that provides no additional logic.
|
||||||
|
*
|
||||||
|
* @author shadowfacts
|
||||||
|
* @param content The [View] that provides the content of this button.
|
||||||
|
* @param padding The padding between the [content] and the edges of the button.
|
||||||
|
*/
|
||||||
|
class Button(content: View, padding: Double = 4.0): AbstractButton<Button>(content, padding)
|
|
@ -21,12 +21,8 @@ class CoordinateConversionTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConvertToParent() {
|
fun testConvertToParent() {
|
||||||
val a = window.addView(View().apply {
|
val a = window.addView(View(Rect(0.0, 0.0, 100.0, 100.0)))
|
||||||
frame = Rect(0.0, 0.0, 100.0, 100.0)
|
val b = a.addSubview(View(Rect(25.0, 25.0, 50.0, 50.0)))
|
||||||
})
|
|
||||||
val b = a.addSubview(View().apply {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
assertEquals(Point(25.0, 25.0), b.convert(Point(0.0, 0.0), to = a))
|
assertEquals(Point(25.0, 25.0), b.convert(Point(0.0, 0.0), to = a))
|
||||||
assertEquals(Point(75.0, 75.0), b.convert(Point(50.0, 50.0), to = a))
|
assertEquals(Point(75.0, 75.0), b.convert(Point(50.0, 50.0), to = a))
|
||||||
|
@ -35,15 +31,9 @@ class CoordinateConversionTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConvertToSibling() {
|
fun testConvertToSibling() {
|
||||||
val root = window.addView(View().apply {
|
val root = window.addView(View(Rect(0.0, 0.0, 200.0, 200.0)))
|
||||||
frame = Rect(0.0, 0.0, 200.0, 200.0)
|
val a = root.addSubview(View(Rect(25.0, 25.0, 50.0, 50.0)))
|
||||||
})
|
val b = root.addSubview(View(Rect(75.0, 75.0, 50.0, 50.0)))
|
||||||
val a = root.addSubview(View().apply {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
val b = root.addSubview(View().apply {
|
|
||||||
frame = Rect(75.0, 75.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
assertEquals(Point(-50.0, -50.0), a.convert(Point(0.0, 0.0), to = b))
|
assertEquals(Point(-50.0, -50.0), a.convert(Point(0.0, 0.0), to = b))
|
||||||
assertEquals(Point(100.0, 100.0), b.convert(Point(50.0, 50.0), to = a))
|
assertEquals(Point(100.0, 100.0), b.convert(Point(50.0, 50.0), to = a))
|
||||||
|
@ -52,21 +42,11 @@ class CoordinateConversionTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConvertBetweenSubtrees() {
|
fun testConvertBetweenSubtrees() {
|
||||||
val root = window.addView(View().apply {
|
val root = window.addView(View(Rect(0.0, 0.0, 200.0, 100.0)))
|
||||||
frame = Rect(0.0, 0.0, 200.0, 100.0)
|
val a = root.addSubview(View(Rect(0.0, 0.0, 100.0, 100.0)))
|
||||||
})
|
val b = root.addSubview(View(Rect(100.0, 0.0, 100.0, 100.0)))
|
||||||
val a = root.addSubview(View().apply {
|
val c = a.addSubview(View(Rect(0.0, 0.0, 50.0, 50.0)))
|
||||||
frame = Rect(0.0, 0.0, 100.0, 100.0)
|
val d = b.addSubview(View(Rect(0.0, 0.0, 50.0, 50.0)))
|
||||||
})
|
|
||||||
val b = root.addSubview(View().apply {
|
|
||||||
frame = Rect(100.0, 0.0, 100.0, 100.0)
|
|
||||||
})
|
|
||||||
val c = a.addSubview(View().apply {
|
|
||||||
frame = Rect(0.0, 0.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
val d = b.addSubview(View().apply {
|
|
||||||
frame = Rect(0.0, 0.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
assertEquals(Point(-100.0, 0.0), c.convert(Point(0.0, 0.0), to = b))
|
assertEquals(Point(-100.0, 0.0), c.convert(Point(0.0, 0.0), to = b))
|
||||||
assertEquals(Point(-50.0, 50.0), c.convert(Point(50.0, 50.0), to = d))
|
assertEquals(Point(-50.0, 50.0), c.convert(Point(50.0, 50.0), to = d))
|
||||||
|
@ -75,12 +55,8 @@ class CoordinateConversionTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConvertBetweenTopLevelViews() {
|
fun testConvertBetweenTopLevelViews() {
|
||||||
val a = window.addView(View().apply {
|
val a = window.addView(View(Rect(0.0, 0.0, 100.0, 100.0)))
|
||||||
frame = Rect(0.0, 0.0, 100.0, 100.0)
|
val b = window.addView(View(Rect(100.0, 100.0, 100.0, 100.0)))
|
||||||
})
|
|
||||||
val b = window.addView(View().apply {
|
|
||||||
frame = Rect(100.0, 100.0, 100.0, 100.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
assertEquals(Point(0.0, 0.0), a.convert(Point(100.0, 100.0), to = b))
|
assertEquals(Point(0.0, 0.0), a.convert(Point(100.0, 100.0), to = b))
|
||||||
assertEquals(Point(200.0, 200.0), b.convert(Point(100.0, 100.0), to = a))
|
assertEquals(Point(200.0, 200.0), b.convert(Point(100.0, 100.0), to = a))
|
||||||
|
@ -89,18 +65,10 @@ class CoordinateConversionTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConvertBetweenTopLevelSubtrees() {
|
fun testConvertBetweenTopLevelSubtrees() {
|
||||||
val a = window.addView(View().apply {
|
val a = window.addView(View(Rect(0.0, 0.0, 100.0, 100.0)))
|
||||||
frame = Rect(0.0, 0.0, 100.0, 100.0)
|
val b = window.addView(View(Rect(100.0, 100.0, 100.0, 100.0)))
|
||||||
})
|
val c = a.addSubview(View(Rect(25.0, 25.0, 50.0, 50.0)))
|
||||||
val b = window.addView(View().apply {
|
val d = b.addSubview(View(Rect(25.0, 25.0, 50.0, 50.0)))
|
||||||
frame = Rect(100.0, 100.0, 100.0, 100.0)
|
|
||||||
})
|
|
||||||
val c = a.addSubview(View().apply {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
val d = b.addSubview(View().apply {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
assertEquals(Point(-50.0, -50.0), c.convert(Point(50.0, 50.0), to = d))
|
assertEquals(Point(-50.0, -50.0), c.convert(Point(50.0, 50.0), to = d))
|
||||||
assertEquals(Point(100.0, 100.0), d.convert(Point(0.0, 0.0), to = c))
|
assertEquals(Point(100.0, 100.0), d.convert(Point(0.0, 0.0), to = c))
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
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.geometry.Size
|
||||||
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
|
import net.shadowfacts.cacao.view.button.Button
|
||||||
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ButtonClickTests {
|
||||||
|
|
||||||
|
lateinit var window: Window
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setup() {
|
||||||
|
window = Window()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testClickInsideButton() {
|
||||||
|
val clicked = CompletableFuture<Boolean>()
|
||||||
|
val content = View().apply {
|
||||||
|
intrinsicContentSize = Size(25.0, 25.0)
|
||||||
|
}
|
||||||
|
val button = window.addView(Button(content).apply {
|
||||||
|
handler = {
|
||||||
|
clicked.complete(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.solver.dsl {
|
||||||
|
button.leftAnchor equalTo 0
|
||||||
|
button.topAnchor equalTo 0
|
||||||
|
}
|
||||||
|
window.layout()
|
||||||
|
window.mouseClicked(Point(5.0, 5.0), MouseButton.LEFT)
|
||||||
|
|
||||||
|
assertTrue(clicked.getNow(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testClickOutsideButton() {
|
||||||
|
val clicked = CompletableFuture<Boolean>()
|
||||||
|
val content = View().apply {
|
||||||
|
intrinsicContentSize = Size(25.0, 25.0)
|
||||||
|
}
|
||||||
|
val button = window.addView(Button(content).apply {
|
||||||
|
handler = {
|
||||||
|
clicked.complete(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.solver.dsl {
|
||||||
|
button.leftAnchor equalTo 0
|
||||||
|
button.topAnchor equalTo 0
|
||||||
|
}
|
||||||
|
window.layout()
|
||||||
|
window.mouseClicked(Point(50.0, 50.0), MouseButton.LEFT)
|
||||||
|
|
||||||
|
assertFalse(clicked.getNow(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,11 +24,7 @@ class ViewClickTests {
|
||||||
@Test
|
@Test
|
||||||
fun testClickInsideRootView() {
|
fun testClickInsideRootView() {
|
||||||
val mouse = CompletableFuture<Point>()
|
val mouse = CompletableFuture<Point>()
|
||||||
window.addView(object: View() {
|
window.addView(object: View(Rect(50.0, 50.0, 100.0, 100.0)) {
|
||||||
init {
|
|
||||||
frame = Rect(50.0, 50.0, 100.0, 100.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
||||||
mouse.complete(point)
|
mouse.complete(point)
|
||||||
}
|
}
|
||||||
|
@ -41,11 +37,7 @@ class ViewClickTests {
|
||||||
@Test
|
@Test
|
||||||
fun testClickOutsideRootView() {
|
fun testClickOutsideRootView() {
|
||||||
val clicked = CompletableFuture<Boolean>()
|
val clicked = CompletableFuture<Boolean>()
|
||||||
window.addView(object: View() {
|
window.addView(object: View(Rect(50.0, 50.0, 100.0, 100.0)) {
|
||||||
init {
|
|
||||||
frame = Rect(50.0, 50.0, 100.0, 100.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
||||||
clicked.complete(true)
|
clicked.complete(true)
|
||||||
}
|
}
|
||||||
|
@ -58,14 +50,8 @@ class ViewClickTests {
|
||||||
@Test
|
@Test
|
||||||
fun testClickInsideNestedView() {
|
fun testClickInsideNestedView() {
|
||||||
val mouse = CompletableFuture<Point>()
|
val mouse = CompletableFuture<Point>()
|
||||||
val root = window.addView(View().apply {
|
val root = window.addView(View(Rect(50.0, 50.0, 100.0, 100.0)))
|
||||||
frame = Rect(50.0, 50.0, 100.0, 100.0)
|
root.addSubview(object: View(Rect(25.0, 25.0, 50.0, 50.0)) {
|
||||||
})
|
|
||||||
root.addSubview(object: View() {
|
|
||||||
init {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
||||||
mouse.complete(point)
|
mouse.complete(point)
|
||||||
}
|
}
|
||||||
|
@ -78,14 +64,8 @@ class ViewClickTests {
|
||||||
@Test
|
@Test
|
||||||
fun testClickOutsideNestedView() {
|
fun testClickOutsideNestedView() {
|
||||||
val clicked = CompletableFuture<Boolean>()
|
val clicked = CompletableFuture<Boolean>()
|
||||||
val root = window.addView(View().apply {
|
val root = window.addView(View(Rect(50.0, 50.0, 100.0, 100.0)))
|
||||||
frame = Rect(50.0, 50.0, 100.0, 100.0)
|
root.addSubview(object: View(Rect(25.0, 25.0, 50.0, 50.0)) {
|
||||||
})
|
|
||||||
root.addSubview(object: View() {
|
|
||||||
init {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
override fun mouseClicked(point: Point, mouseButton: MouseButton) {
|
||||||
clicked.complete(true)
|
clicked.complete(true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,7 @@ class ViewHoverTests {
|
||||||
@Test
|
@Test
|
||||||
fun testHoverRootView() {
|
fun testHoverRootView() {
|
||||||
val point = CompletableFuture<Point>()
|
val point = CompletableFuture<Point>()
|
||||||
window.addView(object: View() {
|
window.addView(object: View(Rect(50.0, 50.0, 100.0, 100.0)) {
|
||||||
init {
|
|
||||||
frame = Rect(50.0, 50.0, 100.0, 100.0)
|
|
||||||
bounds = Rect(0.0, 0.0, 100.0, 100.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawContent(mouse: Point, delta: Float) {
|
override fun drawContent(mouse: Point, delta: Float) {
|
||||||
point.complete(mouse)
|
point.complete(mouse)
|
||||||
}
|
}
|
||||||
|
@ -50,16 +45,8 @@ class ViewHoverTests {
|
||||||
@Test
|
@Test
|
||||||
fun testHoverNestedView() {
|
fun testHoverNestedView() {
|
||||||
val point = CompletableFuture<Point>()
|
val point = CompletableFuture<Point>()
|
||||||
val root = window.addView(View().apply {
|
val root = window.addView(View(Rect(50.0, 50.0, 100.0, 100.0)))
|
||||||
frame = Rect(50.0, 50.0, 100.0, 100.0)
|
root.addSubview(object: View(Rect(25.0, 25.0, 50.0, 50.0)) {
|
||||||
bounds = Rect(0.0, 0.0, 100.0, 100.0)
|
|
||||||
})
|
|
||||||
root.addSubview(object: View() {
|
|
||||||
init {
|
|
||||||
frame = Rect(25.0, 25.0, 50.0, 50.0)
|
|
||||||
bounds = Rect(0.0, 0.0, 50.0, 50.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawContent(mouse: Point, delta: Float) {
|
override fun drawContent(mouse: Point, delta: Float) {
|
||||||
point.complete(mouse)
|
point.complete(mouse)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue