PhysicalConnectivity/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/TabViewController.kt

161 lines
4.3 KiB
Kotlin

package net.shadowfacts.cacao.viewcontroller
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.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: Array<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
private lateinit var tabVCContainer: View
override fun viewDidLoad() {
super.viewDidLoad()
// 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)
tabVCContainer = View()
outerStack.addArrangedSubview(tabVCContainer)
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)
background.zIndex = -1.0
tabVCContainer.addSubview(background)
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
background.leftAnchor equalTo tabVCContainer.leftAnchor
background.rightAnchor equalTo tabVCContainer.rightAnchor
background.topAnchor equalTo tabVCContainer.topAnchor
background.bottomAnchor equalTo tabVCContainer.bottomAnchor
}
}
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)
addSubview(backgroundView)
}
override fun didLayout() {
super.didLayout()
updateBackgroundTexture()
}
fun setSelected(selected: Boolean) {
this.selected = selected
updateBackgroundTexture()
}
override fun getCurrentBackground(mouse: Point) = backgroundView
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)
}
}
}