aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt
blob: 42cf66cd073751afe29a0a02df44c12978d22260 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
 * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

package moe.nea.firmament.gui.config

import io.github.cottonmc.cotton.gui.widget.WButton
import io.github.cottonmc.cotton.gui.widget.data.InputResult
import org.lwjgl.glfw.GLFW
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement
import net.minecraft.client.util.InputUtil
import net.minecraft.text.Text
import net.minecraft.util.Formatting
import moe.nea.firmament.keybindings.FirmamentKeyBindings
import moe.nea.firmament.keybindings.SavedKeyBinding

class KeyBindingHandler(name: String, managedConfig: ManagedConfig) : ManagedConfig.OptionHandler<SavedKeyBinding> {
    init {
        FirmamentKeyBindings.registerKeyBinding(name, managedConfig)
    }

    override fun toJson(element: SavedKeyBinding): JsonElement? {
        return Json.encodeToJsonElement(element)
    }

    override fun fromJson(element: JsonElement): SavedKeyBinding {
        return Json.decodeFromJsonElement(element)
    }

    override fun emitGuiElements(opt: ManagedOption<SavedKeyBinding>, guiAppender: GuiAppender) {
        var editing = false
        var lastPressed = 0
        var lastPressedNonModifier = 0
        var updateButton: (() -> Unit)? = null
        val button = object : WButton() {
            override fun onKeyPressed(ch: Int, key: Int, modifiers: Int): InputResult {
                if (!editing) {
                    return super.onKeyPressed(ch, key, modifiers)
                }
                if (ch == GLFW.GLFW_KEY_ESCAPE) {
                    lastPressedNonModifier = 0
                    editing = false
                    lastPressed = 0
                    opt.value = SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN)
                    updateButton!!()
                    return InputResult.PROCESSED
                }
                if (ch == GLFW.GLFW_KEY_LEFT_SHIFT || ch == GLFW.GLFW_KEY_RIGHT_SHIFT
                    || ch == GLFW.GLFW_KEY_LEFT_ALT || ch == GLFW.GLFW_KEY_RIGHT_ALT
                    || ch == GLFW.GLFW_KEY_LEFT_CONTROL || ch == GLFW.GLFW_KEY_RIGHT_CONTROL
                ) {
                    lastPressed = ch
                } else {
                    opt.value = SavedKeyBinding(
                        ch, modifiers
                    )
                    editing = false
                    lastPressed = 0
                    lastPressedNonModifier = 0
                }
                updateButton!!()
                return InputResult.PROCESSED
            }

            override fun onFocusLost() {
                super.onFocusLost()
                lastPressedNonModifier = 0
                editing = false
                lastPressed = 0
                updateButton!!()
            }

            override fun onKeyReleased(ch: Int, key: Int, modifiers: Int): InputResult {
                if (!editing)
                    return super.onKeyReleased(ch, key, modifiers)
                if (lastPressedNonModifier == ch || (lastPressedNonModifier == 0 && ch == lastPressed)) {
                    opt.value = SavedKeyBinding(
                        ch, modifiers
                    )
                    editing = false
                    lastPressed = 0
                    lastPressedNonModifier = 0
                }
                updateButton!!()
                return InputResult.PROCESSED
            }
        }

        fun updateLabel() {
            val stroke = Text.literal("")
            if (opt.value.shift) {
                stroke.append("SHIFT + ") // TODO: translations?
            }
            if (opt.value.alt) {
                stroke.append("ALT + ")
            }
            if (opt.value.ctrl) {
                stroke.append("CTRL + ")
            }
            stroke.append(InputUtil.Type.KEYSYM.createFromCode(opt.value.keyCode).localizedText)
            if (editing)
                stroke.styled { it.withColor(Formatting.YELLOW) }
            button.setLabel(stroke)
        }
        updateButton = ::updateLabel
        updateButton()
        button.setOnClick {
            editing = true
            button.requestFocus()
            updateButton()
        }
        guiAppender.appendLabeledRow(opt.labelText, button)
    }

}