aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt
blob: 13c659223a8c7b3e47c1385ccfd55e3418a589fa (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * 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.notenoughupdates.moulconfig.common.IMinecraft
import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
import io.github.notenoughupdates.moulconfig.deps.libninepatch.NinePatch
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
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.text.Text
import net.minecraft.util.Formatting
import moe.nea.firmament.gui.FirmButtonComponent
import moe.nea.firmament.keybindings.FirmamentKeyBindings
import moe.nea.firmament.keybindings.SavedKeyBinding

class KeyBindingHandler(val name: String, val managedConfig: ManagedConfig) :
    ManagedConfig.OptionHandler<SavedKeyBinding> {

    override fun initOption(opt: ManagedOption<SavedKeyBinding>) {
        FirmamentKeyBindings.registerKeyBinding(name, opt)
    }

    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 label: String = ""
        var button: FirmButtonComponent? = null
        fun updateLabel() {
            var stroke = opt.value.format()
            if (editing) {
                stroke = Text.literal("")
                val (shift, alt, ctrl) = SavedKeyBinding.getMods(SavedKeyBinding.getModInt())
                if (shift) {
                    stroke.append("SHIFT + ")
                }
                if (alt) {
                    stroke.append("ALT + ")
                }
                if (ctrl) {
                    stroke.append("CTRL + ")
                }
                stroke.append("???")
                stroke.styled { it.withColor(Formatting.YELLOW) }
            }
            label = (stroke).string
            managedConfig.save()
        }
        button = object : FirmButtonComponent(
            TextComponent(
                IMinecraft.instance.defaultFontRenderer,
                { label },
                130,
                TextComponent.TextAlignment.LEFT,
                false,
                false
            ), action = {
                if (editing) {
                    button!!.blur()
                } else {
                    editing = true
                    button!!.requestFocus()
                    updateLabel()
                }
            }) {
            override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
                if (event is KeyboardEvent.KeyPressed) {
                    return if (event.pressed) onKeyPressed(event.keycode, SavedKeyBinding.getModInt())
                    else onKeyReleased(event.keycode, SavedKeyBinding.getModInt())
                }
                return super.keyboardEvent(event, context)
            }

            override fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
                if (editing) return activeBg
                return super.getBackground(context)
            }

            fun onKeyPressed(ch: Int, modifiers: Int): Boolean {
                if (!editing) {
                    return false
                }
                if (ch == GLFW.GLFW_KEY_ESCAPE) {
                    lastPressedNonModifier = 0
                    editing = false
                    lastPressed = 0
                    opt.value = SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN)
                    updateLabel()
                    blur()
                    return true
                }
                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
                    blur()
                    lastPressed = 0
                    lastPressedNonModifier = 0
                }
                updateLabel()
                return true
            }

            override fun onLostFocus() {
                lastPressedNonModifier = 0
                editing = false
                lastPressed = 0
                updateLabel()
            }

            fun onKeyReleased(ch: Int, modifiers: Int): Boolean {
                if (!editing)
                    return false
                if (lastPressedNonModifier == ch || (lastPressedNonModifier == 0 && ch == lastPressed)) {
                    opt.value = SavedKeyBinding(ch, modifiers)
                    editing = false
                    blur()
                    lastPressed = 0
                    lastPressedNonModifier = 0
                }
                updateLabel()
                return true
            }
        }
        updateLabel()
        guiAppender.appendLabeledRow(opt.labelText, button)
    }

}