Exit Full View

Games Cupboard / gamescupboard-client / src / commonMain / kotlin / uk / co / nickthecoder / gamescupboard / client / Dock.kt

package uk.co.nickthecoder.gamescupboard.client

import com.soywiz.klock.seconds
import com.soywiz.korge.input.mouse
import com.soywiz.korge.tween.get
import com.soywiz.korge.view.*
import com.soywiz.korma.geom.degrees
import com.soywiz.korma.interpolation.Easing
import uk.co.nickthecoder.gamescupboard.common.dockWidth
import uk.co.nickthecoder.gamescupboard.common.playingAreaWidth

/**
 * The right edge of the window contains a set of "buttons", one for each [Dockable].
 * Click the button, and the [Dockable] will slide into view. Click again to hide it.
 * If you click a button while a different dockable is visible, then the old dockable
 * is hidden before showing the new one.
 */
class Dock(width: Double, height: Double, dockables: List<Dockable>) : FixedSizeContainer(width, height) {

    private var spacing = 8.0

    private var selectedDockable: Dockable? = null
    private var buttonY = 10.0

    private val buttons = Container()

    init {
        solidRect(width, height, dockColor)
        addChild(buttons)

        for (dockable in dockables) {
            add(dockable)
        }
    }

    fun doNotCoverPlayingArea(immediately: Boolean) {
        selectedDockable?.let {
            if (it.panel.globalX < playingAreaWidth) {
                it.hide(immediately)
                selectedDockable = null
            }
        }
    }

    fun add(dockable: Dockable) {

        dockable.panel.position(0.0, 0.0)
        addChildAt(dockable.panel, 0)

        val button = dockable.button
        button.y = buttonY
        button.mouse.click.add { selectDockable(dockable) }

        buttons.addChild(button)
        buttonY += button.height + spacing
    }

    private fun selectDockable(dockable: Dockable) {
        if (dockable === selectedDockable) {
            dockable.hide(false)
            selectedDockable = null
            return
        }

        selectedDockable?.hide(true)
        selectedDockable = dockable
        dockable.show()
    }

}

interface Dockable {

    val button: View
    val panel: View

    fun show()
    fun hide(immediately: Boolean)
}

abstract class TextButtonDockable(labelStr: String) : Dockable {

    val margin = 10.0

    val label = Text(labelStr).apply {
        rotation = 90.degrees
        x = height + (dockWidth - height) / 2
        y = margin
    }
    val box = SolidRect(dockWidth, label.width + margin * 2, dockButtonColor)

    override val button = Container().apply {
        addChild(box)
        addChild(label)
    }

    override fun show() {
        box.color = dockButtonSelectedColor
        panel.launchTween(panel::x[-panel.width], time = 0.3.seconds, easing = Easing.EASE_IN)
    }

    override fun hide(immediately: Boolean) {
        box.color = dockButtonColor
        if (immediately) {
            panel.x = 0.0
        } else {
            panel.launchTween(panel::x[0.0], time = 0.3.seconds, easing = Easing.EASE_IN)
        }
    }
}