package net.shadowfacts.cacao.view.button import net.minecraft.util.Identifier import net.shadowfacts.cacao.Window import net.shadowfacts.cacao.geometry.Axis import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.texture.NinePatchTexture import net.shadowfacts.cacao.util.texture.Texture import net.shadowfacts.cacao.util.properties.ResettableLazyProperty 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.kiwidsl.dsl /** * A button that provides a dropdown for the user to select from a list of values. * The button itself shows a [ContentView] representing the currently selected [Value] and an image indicator that serves * as a hint for the ability to click the button and display the dropdown. * * The dropdown list itself is displayed by presenting a new [Window] at the front of the window stack. * Each possible value is represented in the list by a button containing a [ContentView] for that value, with the button * for the current value being disabled. * * @author shadowfacts * @param Value The type of value that the dropdown selects. * @param ContentView The specific type of the [View] that represents selected item in the button and each item in the dropdown list. * @param initialValue The initial value of the dropdown button. * @param allValues List of all allowed values for the dropdown. * @param createView A function that creates a [ContentView] representing the given [Value]. * Positioning of content views is handled by the dropdown. * @param updateView A function for updating the view used as the button's 'label' that's visible even when the dropdown isn't. */ class DropdownButton( val initialValue: Value, val allValues: Iterable, val createView: (Value) -> ContentView, val updateView: (newValue: Value, view: ContentView) -> Unit, padding: Double = 4.0 ): AbstractButton>( StackView(Axis.HORIZONTAL), padding ) { companion object { val DROPDOWN_INDICATOR = Texture(Identifier("asmr", "textures/gui/dropdown.png"), 0, 0) } private val stackView: StackView get() = content as StackView private val contentView: ContentView get() = stackView.arrangedSubviews.first() as ContentView private lateinit var dropdownIndicator: TextureView /** * The currently selected [Value] of the dropdown. */ var value: Value = initialValue set(value) { field = value updateView(value, contentView) // todo: setNeedsLayout instead of force unwrapping window window!!.layout() } override fun wasAdded() { super.wasAdded() stackView.addArrangedSubview(createView(initialValue)) dropdownIndicator = stackView.addArrangedSubview(TextureView(DROPDOWN_INDICATOR)) solver.dsl { dropdownIndicator.widthAnchor equalTo 9 dropdownIndicator.heightAnchor equalTo 9 } } override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean { return if (mouseButton == MouseButton.LEFT || mouseButton == MouseButton.RIGHT) { showDropdown() true } else { super.mouseClicked(point, mouseButton) } } private fun showDropdown() { // val dropdownWindow = window.screen.addWindow(Window()) // val dropdownBackground = dropdownWindow.addView(NinePatchView(NinePatchTexture.BUTTON_BG).apply { // zIndex = -1.0 // }) // val stack = dropdownWindow.addView(StackView(Axis.VERTICAL, StackView.Distribution.FILL)) // lateinit var selectedButton: View // val buttons = mutableListOf