ASMR/src/main/kotlin/net/shadowfacts/asmr/ui/ProgramBlockView.kt

107 lines
4.0 KiB
Kotlin

package net.shadowfacts.asmr.ui
import net.minecraft.util.Identifier
import net.shadowfacts.asmr.ASMR
import net.shadowfacts.asmr.program.ExecutableBlock
import net.shadowfacts.asmr.program.ProgramBlock
import net.shadowfacts.cacao.geometry.Axis
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.Color
import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.texture.Texture
import net.shadowfacts.cacao.view.Label
import net.shadowfacts.cacao.view.StackView
import net.shadowfacts.cacao.view.TextureView
import net.shadowfacts.cacao.view.View
import net.shadowfacts.kiwidsl.dsl
import no.birkett.kiwi.Constraint
/**
* @author shadowfacts
*/
class ProgramBlockView(val block: ProgramBlock): StackView(Axis.VERTICAL, Distribution.CENTER, spacing = 4.0) {
companion object {
val executionFlowInactiveTexture = Texture(Identifier(ASMR.modid, "textures/gui/programmer/execution_flow.png"), u = 0, v = 0)
val executionFlowActiveTexture = Texture(Identifier(ASMR.modid, "textures/gui/programmer/execution_flow.png"), u = 7, v = 0)
}
var incomingExecution: View? = null
var outgoingExeuction: View? = null
var xConstraint: Constraint? = null
var yConstraint: Constraint? = null
override fun wasAdded() {
super.wasAdded()
respondsToDragging = true
backgroundColor = Color.BLACK
zIndex = 10.0
val titleStack = addArrangedSubview(StackView(Axis.HORIZONTAL, Distribution.CENTER))
val title = titleStack.addArrangedSubview(Label(block.javaClass.simpleName))
if (block is ExecutableBlock) {
val incomingTexture = if (block.executionFlow.prev == null) executionFlowInactiveTexture else executionFlowActiveTexture
incomingExecution = titleStack.addArrangedSubview(TextureView(incomingTexture), index = 0)
val outgoingTexture = if (block.executionFlow.next == null) executionFlowInactiveTexture else executionFlowActiveTexture
outgoingExeuction = titleStack.addArrangedSubview(TextureView(outgoingTexture))
}
val pairs = block.inputs.zip(block.outputs)
val remainingInputs = if (block.inputs.size > block.outputs.size) block.inputs.drop(block.outputs.size) else listOf()
val remainingOutputs = if (block.outputs.size > block.inputs.size) block.outputs.drop(block.inputs.size) else listOf()
for ((input, output) in pairs) {
val hStack = addArrangedSubview(StackView(Axis.HORIZONTAL, spacing = 8.0))
hStack.addArrangedSubview(Label(input.identifier.toString()))
hStack.addArrangedSubview(Label(output.identifier.toString()))
}
for (input in remainingInputs) {
addArrangedSubview(Label(input.identifier.toString()))
}
for (output in remainingOutputs) {
addArrangedSubview(Label(output.identifier.toString(), textAlignment = Label.TextAlignment.RIGHT))
}
solver.dsl {
// we have to constrain the titleStack height, because it's distribution is set to CENTER, so it doesn't do it itself
titleStack.heightAnchor equalTo title.heightAnchor
widthAnchor greaterThanOrEqualTo titleStack.widthAnchor
if (block is ExecutableBlock) {
incomingExecution!!.widthAnchor equalTo incomingExecution!!.heightAnchor
incomingExecution!!.widthAnchor equalTo 7
outgoingExeuction!!.widthAnchor equalTo outgoingExeuction!!.heightAnchor
outgoingExeuction!!.widthAnchor equalTo 7
}
for (view in arrangedSubviews.drop(1)) {
widthAnchor.equalTo(view.widthAnchor, strength = STRONG)
}
}
updateDraggingConstraints()
}
override fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
block.position += delta
updateDraggingConstraints()
return true
}
private fun updateDraggingConstraints() {
if (xConstraint != null) solver.removeConstraint(xConstraint)
if (yConstraint != null) solver.removeConstraint(yConstraint)
solver.dsl {
xConstraint = (leftAnchor equalTo superview!!.leftAnchor + block.position.x)
yConstraint = (topAnchor equalTo superview!!.topAnchor + block.position.y)
}
window!!.layout()
}
override fun drawContent(mouse: Point, delta: Float) {
super.drawContent(mouse, delta)
}
}