Exit Full View

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

package uk.co.nickthecoder.gamescupboard.client.text
/*
  This is an almost identical copy of UITextInput (part of the Korge UI components).
  There were bugs in TextEditController, and to fix those bugs, I made a copy
  of both classes with different names.
 */

import com.soywiz.korev.ISoftKeyboardConfig
import com.soywiz.korev.SoftKeyboardConfig
import com.soywiz.korge.annotations.KorgeExperimental
import com.soywiz.korge.ui.BoxUISkin
import com.soywiz.korge.ui.UIView
import com.soywiz.korge.ui.blur
import com.soywiz.korge.ui.focus
import com.soywiz.korge.view.Container
import com.soywiz.korge.view.ViewDslMarker
import com.soywiz.korge.view.ViewRenderer
import com.soywiz.korge.view.addTo
import com.soywiz.korge.view.bounds
import com.soywiz.korge.view.clipContainer
import com.soywiz.korge.view.renderableView
import com.soywiz.korge.view.text
import com.soywiz.korim.color.Colors
import com.soywiz.korim.font.Font
import com.soywiz.korio.async.Signal
import com.soywiz.korma.geom.Margin
import com.soywiz.korma.geom.Rectangle
import com.soywiz.korma.geom.without

inline fun Container.textInput(
    initialText: String = "",
    width: Double = 128.0,
    height: Double = 24.0,
    skin: ViewRenderer = BoxUISkin(),
    block: @ViewDslMarker TextInput.() -> Unit = {}
): TextInput = TextInput(initialText, width, height, skin)
    .addTo(this).also { block(it) }

/**
 * Simple Single Line Text Input
 */
@OptIn(KorgeExperimental::class)
class TextInput(
    initialText: String = "",
    width: Double = 128.0,
    height: Double = 24.0,
    skin: ViewRenderer = BoxUISkin()
) :
    UIView(width, height),
    ISoftKeyboardConfig by SoftKeyboardConfig() {

    private val bg = renderableView(width, height, skin)
    var skin by bg::viewRenderer
    private val container = clipContainer(0.0, 0.0)

    private val textView = container.text(initialText, 16.0, color = Colors.BLACK)
    val controller = TextInputController(textView, textView, this, bg)


    var text: String by controller::text
    var textSize: Double by controller::textSize
    var font: Font by controller::font
    val onReturnPressed: Signal<TextInputController> by controller::onReturnPressed
    val onEscPressed: Signal<TextInputController> by controller::onEscPressed
    val onFocusLost: Signal<TextInputController> by controller::onFocusLost
    var selectionRange: IntRange by controller::selectionRange
    var selectionStart: Int by controller::selectionStart
    var selectionEnd: Int by controller::selectionEnd
    val selectionLength: Int by controller::selectionLength
    fun focus() = controller.focus()
    fun blur() = controller.blur()
    fun selectAll() = controller.selectAll()

    var padding: Margin = Margin(3.0, 2.0, 2.0, 2.0)
        set(value) {
            field = value
            onSizeChanged()
        }

    override fun onSizeChanged() {
        bg.setSize(width, height)
        container.bounds(Rectangle(0.0, 0.0, width, height).without(padding))
    }

    init {
        onSizeChanged()
    }

}