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( val tabs: Array, 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> 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) { 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( val tab: T, ): AbstractButton>( 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) } } }