ASMR/src/main/kotlin/net/shadowfacts/cacao/view/View.kt

130 lines
3.6 KiB
Kotlin
Raw Normal View History

2019-06-22 19:02:17 +00:00
package net.shadowfacts.cacao.view
2019-06-21 20:22:23 +00:00
import com.mojang.blaze3d.platform.GlStateManager
import net.shadowfacts.kiwidsl.dsl
2019-06-22 19:02:17 +00:00
import net.shadowfacts.cacao.LayoutVariable
import net.shadowfacts.cacao.geometry.Axis
import net.shadowfacts.cacao.geometry.AxisPosition
import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.geometry.Size
import net.shadowfacts.cacao.util.Color
import net.shadowfacts.cacao.util.RenderHelper
2019-06-22 14:21:29 +00:00
import no.birkett.kiwi.Constraint
2019-06-21 20:22:23 +00:00
import no.birkett.kiwi.Solver
2019-06-22 14:59:18 +00:00
/**
* @author shadowfacts
*/
2019-06-22 14:56:12 +00:00
open class View {
2019-06-21 20:22:23 +00:00
lateinit var solver: Solver
// in the coordinate system of the screen
val leftAnchor = LayoutVariable(this, "left")
val rightAnchor = LayoutVariable(this, "right")
val topAnchor = LayoutVariable(this, "top")
val bottomAnchor = LayoutVariable(this, "bottom")
val widthAnchor = LayoutVariable(this, "width")
val heightAnchor = LayoutVariable(this, "height")
val centerXAnchor = LayoutVariable(this, "centerX")
val centerYAnchor = LayoutVariable(this, "centerY")
// The rectangle for this view in the coordinate system of the parent view.
lateinit var frame: Rect
2019-06-21 20:22:23 +00:00
// The rectangle for this view in its own coordinate system.
lateinit var bounds: Rect
2019-06-21 20:22:23 +00:00
2019-06-22 14:21:29 +00:00
var intrinsicContentSize: Size? = null
set(value) {
updateIntrinsicContentSizeConstraints(intrinsicContentSize, value)
field = value
}
private var intrinsicContentSizeWidthConstraint: Constraint? = null
private var intrinsicContentSizeHeightConstraint: Constraint? = null
2019-06-22 14:56:12 +00:00
var backgroundColor = Color.CLEAR
2019-06-21 20:22:23 +00:00
var parent: View? = null
val subviews = mutableListOf<View>()
2019-06-21 20:22:23 +00:00
2019-06-22 18:59:37 +00:00
fun getAnchor(axis: Axis, position: AxisPosition): LayoutVariable {
return when (axis) {
Axis.HORIZONTAL ->
when (position) {
AxisPosition.LEADING -> leftAnchor
AxisPosition.CENTER -> centerXAnchor
AxisPosition.TRAILING -> rightAnchor
}
Axis.VERTICAL ->
when (position) {
AxisPosition.LEADING -> topAnchor
AxisPosition.CENTER -> centerYAnchor
AxisPosition.TRAILING -> bottomAnchor
}
}
}
fun addSubview(view: View): View {
2019-06-21 20:22:23 +00:00
subviews.add(view)
view.parent = this
view.solver = solver
view.wasAdded()
return view
2019-06-21 20:22:23 +00:00
}
2019-06-22 14:56:12 +00:00
open fun wasAdded() {
2019-06-21 20:22:23 +00:00
createInternalConstraints()
2019-06-22 18:59:37 +00:00
updateIntrinsicContentSizeConstraints(null, intrinsicContentSize)
2019-06-21 20:22:23 +00:00
}
2019-06-22 14:56:12 +00:00
open fun createInternalConstraints() {
2019-06-21 20:22:23 +00:00
solver.dsl {
rightAnchor equalTo (leftAnchor + widthAnchor)
bottomAnchor equalTo (topAnchor + heightAnchor)
centerXAnchor equalTo (leftAnchor + widthAnchor / 2)
centerYAnchor equalTo (topAnchor + heightAnchor / 2)
}
}
2019-06-22 14:21:29 +00:00
private fun updateIntrinsicContentSizeConstraints(old: Size?, new: Size?) {
2019-06-22 18:59:37 +00:00
if (!this::solver.isInitialized) return
2019-06-22 14:21:29 +00:00
if (old != null) {
solver.removeConstraint(intrinsicContentSizeWidthConstraint!!)
solver.removeConstraint(intrinsicContentSizeHeightConstraint!!)
}
if (new != null) {
solver.dsl {
this@View.intrinsicContentSizeWidthConstraint = (widthAnchor.equalTo(new.width, strength = WEAK))
this@View.intrinsicContentSizeHeightConstraint = (heightAnchor.equalTo(new.height, strength = WEAK))
}
}
}
2019-06-22 14:56:12 +00:00
open fun didLayout() {
subviews.forEach(View::didLayout)
2019-06-21 20:22:23 +00:00
val parentLeft = parent?.leftAnchor?.value ?: 0.0
val parentTop = parent?.topAnchor?.value ?: 0.0
frame = Rect(leftAnchor.value - parentLeft, topAnchor.value - parentTop, widthAnchor.value, heightAnchor.value)
bounds = Rect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
2019-06-21 20:22:23 +00:00
}
fun draw() {
GlStateManager.pushMatrix()
GlStateManager.translated(frame.left, frame.top, 0.0)
RenderHelper.fill(bounds, backgroundColor)
drawContent()
subviews.forEach(View::draw)
2019-06-21 20:22:23 +00:00
GlStateManager.popMatrix()
}
2019-06-22 14:56:12 +00:00
open fun drawContent() {}
2019-06-21 20:22:23 +00:00
}