178 lines
4.8 KiB
Kotlin
178 lines
4.8 KiB
Kotlin
package net.shadowfacts.cacao.viewcontroller
|
|
|
|
import net.minecraft.client.util.math.MatrixStack
|
|
import net.minecraft.text.Text
|
|
import net.minecraft.util.Identifier
|
|
import net.shadowfacts.cacao.geometry.Axis
|
|
import net.shadowfacts.cacao.geometry.Point
|
|
import net.shadowfacts.cacao.geometry.Rect
|
|
import net.shadowfacts.cacao.geometry.Size
|
|
import net.shadowfacts.cacao.util.Color
|
|
import net.shadowfacts.cacao.util.MouseButton
|
|
import net.shadowfacts.cacao.util.texture.NinePatchTexture
|
|
import net.shadowfacts.cacao.util.texture.Texture
|
|
import net.shadowfacts.cacao.view.NinePatchView
|
|
import net.shadowfacts.cacao.view.StackView
|
|
import net.shadowfacts.cacao.view.TextureView
|
|
import net.shadowfacts.cacao.view.View
|
|
import net.shadowfacts.cacao.view.button.AbstractButton
|
|
import net.shadowfacts.kiwidsl.dsl
|
|
|
|
/**
|
|
* @author shadowfacts
|
|
*/
|
|
class TabViewController<T: TabViewController.Tab>(
|
|
val tabs: List<T>,
|
|
initalTab: T = tabs.first()
|
|
): ViewController() {
|
|
|
|
interface Tab {
|
|
val tabView: View
|
|
val tooltip: Text?
|
|
val controller: ViewController
|
|
}
|
|
|
|
var currentTab: T = initalTab
|
|
private set
|
|
|
|
private lateinit var tabButtons: List<TabButton<T>>
|
|
|
|
private lateinit var outerStack: StackView
|
|
private lateinit var tabStack: StackView
|
|
// todo: this shouldn't be public, use layout guides
|
|
lateinit var tabVCContainer: View
|
|
private set
|
|
|
|
override fun viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
// todo: might be simpler to just not use a stack view
|
|
// padding is -4 so tab button texture overlaps with panel BG as expected
|
|
outerStack = StackView(Axis.VERTICAL, StackView.Distribution.FILL, -4.0)
|
|
view.addSubview(outerStack)
|
|
|
|
tabStack = StackView(Axis.HORIZONTAL, StackView.Distribution.FILL)
|
|
tabStack.zIndex = 1.0
|
|
outerStack.addArrangedSubview(tabStack)
|
|
|
|
tabButtons = tabs.mapIndexed { index, tab ->
|
|
val btn = TabButton(tab)
|
|
btn.handler = this::selectTab
|
|
if (tab == currentTab) {
|
|
btn.setSelected(true)
|
|
}
|
|
btn
|
|
}
|
|
// todo: batch calls to addArrangedSubview
|
|
tabButtons.forEach(tabStack::addArrangedSubview)
|
|
|
|
// spacer
|
|
tabStack.addArrangedSubview(View())
|
|
|
|
val background = NinePatchView(NinePatchTexture.PANEL_BG)
|
|
outerStack.addArrangedSubview(background)
|
|
|
|
tabVCContainer = View()
|
|
tabVCContainer.zIndex = 1.0
|
|
view.addSubview(tabVCContainer)
|
|
|
|
embedChild(currentTab.controller, tabVCContainer)
|
|
|
|
view.solver.dsl {
|
|
outerStack.leftAnchor equalTo view.leftAnchor
|
|
outerStack.rightAnchor equalTo view.rightAnchor
|
|
outerStack.topAnchor equalTo view.topAnchor
|
|
outerStack.bottomAnchor equalTo view.bottomAnchor
|
|
|
|
tabVCContainer.leftAnchor equalTo (background.leftAnchor + 6)
|
|
tabVCContainer.rightAnchor equalTo (background.rightAnchor - 6)
|
|
tabVCContainer.topAnchor equalTo (background.topAnchor + 6)
|
|
tabVCContainer.bottomAnchor equalTo (background.bottomAnchor - 6)
|
|
}
|
|
}
|
|
|
|
private fun selectTab(button: TabButton<T>) {
|
|
val oldTab = currentTab
|
|
currentTab = button.tab
|
|
|
|
// todo: unselect old button
|
|
tabButtons.forEach { it.setSelected(false) }
|
|
oldTab.controller.removeFromParent()
|
|
|
|
button.setSelected(true)
|
|
embedChild(currentTab.controller, tabVCContainer)
|
|
// todo: setNeedsLayout
|
|
window!!.layout()
|
|
}
|
|
|
|
private class TabButton<T: Tab>(
|
|
val tab: T,
|
|
): AbstractButton<TabButton<T>>(
|
|
tab.tabView,
|
|
padding = 2.0
|
|
) {
|
|
companion object {
|
|
val BACKGROUND = Identifier("textures/gui/container/creative_inventory/tabs.png")
|
|
}
|
|
|
|
private var selected = false
|
|
private var backgroundView = TextureView(Texture(BACKGROUND, 0, 0))
|
|
|
|
init {
|
|
intrinsicContentSize = Size(28.0, 32.0)
|
|
background = null
|
|
hoveredBackground = null
|
|
disabledBackground = null
|
|
}
|
|
|
|
override fun wasAdded() {
|
|
super.wasAdded()
|
|
backgroundView.usesConstraintBasedLayout = false
|
|
backgroundView.frame = Rect(0.0, 0.0, 28.0, 32.0)
|
|
backgroundView.zIndex = -1.0
|
|
addSubview(backgroundView)
|
|
solver.dsl {
|
|
content.bottomAnchor lessThanOrEqualTo (bottomAnchor - 4)
|
|
}
|
|
}
|
|
|
|
override fun didLayout() {
|
|
super.didLayout()
|
|
updateBackgroundTexture()
|
|
}
|
|
|
|
fun setSelected(selected: Boolean) {
|
|
this.selected = selected
|
|
updateBackgroundTexture()
|
|
}
|
|
|
|
override fun getCurrentBackground(mouse: Point) = backgroundView
|
|
|
|
override fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
|
super.draw(matrixStack, mouse, delta)
|
|
|
|
if (mouse in bounds && tab.tooltip != null) {
|
|
window!!.drawTooltip(listOf(tab.tooltip!!))
|
|
}
|
|
}
|
|
|
|
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
|
|
if (selected) return false
|
|
else return super.mouseClicked(point, mouseButton)
|
|
}
|
|
|
|
private fun updateBackgroundTexture() {
|
|
val v = if (selected) 32 else 0
|
|
val u = when {
|
|
superview == null -> 0
|
|
frame.left == 0.0 -> 0
|
|
frame.right == superview!!.bounds.right -> 140
|
|
else -> 28
|
|
}
|
|
backgroundView.texture = Texture(BACKGROUND, u, v)
|
|
backgroundView.frame = Rect(0.0, 0.0, 28.0, if (selected) 32.0 else 28.0)
|
|
}
|
|
}
|
|
|
|
}
|