aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/gui')
-rw-r--r--src/main/kotlin/gui/CheckboxComponent.kt56
-rw-r--r--src/main/kotlin/gui/config/ChoiceHandler.kt47
-rw-r--r--src/main/kotlin/gui/config/EnumRenderer.kt15
-rw-r--r--src/main/kotlin/gui/config/ManagedConfig.kt24
4 files changed, 142 insertions, 0 deletions
diff --git a/src/main/kotlin/gui/CheckboxComponent.kt b/src/main/kotlin/gui/CheckboxComponent.kt
new file mode 100644
index 0000000..761c086
--- /dev/null
+++ b/src/main/kotlin/gui/CheckboxComponent.kt
@@ -0,0 +1,56 @@
+package moe.nea.firmament.gui
+
+import io.github.notenoughupdates.moulconfig.gui.GuiComponent
+import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
+import io.github.notenoughupdates.moulconfig.gui.MouseEvent
+import io.github.notenoughupdates.moulconfig.observer.GetSetter
+import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
+import net.minecraft.client.render.RenderLayer
+import moe.nea.firmament.Firmament
+
+class CheckboxComponent<T>(
+ val state: GetSetter<T>,
+ val value: T,
+) : GuiComponent() {
+ override fun getWidth(): Int {
+ return 16
+ }
+
+ override fun getHeight(): Int {
+ return 16
+ }
+
+ fun isEnabled(): Boolean {
+ return state.get() == value
+ }
+
+ override fun render(context: GuiImmediateContext) {
+ val ctx = (context.renderContext as ModernRenderContext).drawContext
+ ctx.drawGuiTexture(
+ RenderLayer::getGuiTextured,
+ if (isEnabled()) Firmament.identifier("firmament:widget/checkbox_checked")
+ else Firmament.identifier("firmament:widget/checkbox_unchecked"),
+ 0, 0,
+ 16, 16
+ )
+ }
+
+ var isClicking = false
+
+ override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
+ if (mouseEvent is MouseEvent.Click) {
+ if (isClicking && !mouseEvent.mouseState && mouseEvent.mouseButton == 0) {
+ isClicking = false
+ if (context.isHovered)
+ state.set(value)
+ return true
+ }
+ if (mouseEvent.mouseState && mouseEvent.mouseButton == 0 && context.isHovered) {
+ requestFocus()
+ isClicking = true
+ return true
+ }
+ }
+ return false
+ }
+}
diff --git a/src/main/kotlin/gui/config/ChoiceHandler.kt b/src/main/kotlin/gui/config/ChoiceHandler.kt
new file mode 100644
index 0000000..25e885a
--- /dev/null
+++ b/src/main/kotlin/gui/config/ChoiceHandler.kt
@@ -0,0 +1,47 @@
+package moe.nea.firmament.gui.config
+
+import io.github.notenoughupdates.moulconfig.gui.HorizontalAlign
+import io.github.notenoughupdates.moulconfig.gui.VerticalAlign
+import io.github.notenoughupdates.moulconfig.gui.component.AlignComponent
+import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
+import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
+import kotlinx.serialization.json.JsonElement
+import kotlin.jvm.optionals.getOrNull
+import net.minecraft.util.StringIdentifiable
+import moe.nea.firmament.gui.CheckboxComponent
+import moe.nea.firmament.util.ErrorUtil
+import moe.nea.firmament.util.json.KJsonOps
+
+class ChoiceHandler<E>(
+ val universe: List<E>,
+) : ManagedConfig.OptionHandler<E> where E : Enum<E>, E : StringIdentifiable {
+ val codec = StringIdentifiable.createCodec {
+ @Suppress("UNCHECKED_CAST", "PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+ (universe as java.util.List<*>).toArray(arrayOfNulls<Enum<E>>(0)) as Array<E>
+ }
+ val renderer = EnumRenderer.default<E>()
+
+ override fun toJson(element: E): JsonElement? {
+ return codec.encodeStart(KJsonOps.INSTANCE, element)
+ .promotePartial { ErrorUtil.softError("Failed to encode json element '$element': $it") }.result()
+ .getOrNull()
+ }
+
+ override fun fromJson(element: JsonElement): E {
+ return codec.decode(KJsonOps.INSTANCE, element)
+ .promotePartial { ErrorUtil.softError("Failed to decode json element '$element': $it") }
+ .result()
+ .get()
+ .first
+ }
+
+ override fun emitGuiElements(opt: ManagedOption<E>, guiAppender: GuiAppender) {
+ guiAppender.appendFullRow(TextComponent(opt.labelText.string))
+ for (e in universe) {
+ guiAppender.appendFullRow(RowComponent(
+ AlignComponent(CheckboxComponent(opt, e), { HorizontalAlign.LEFT }, { VerticalAlign.CENTER }),
+ TextComponent(renderer.getName(opt, e).string)
+ ))
+ }
+ }
+}
diff --git a/src/main/kotlin/gui/config/EnumRenderer.kt b/src/main/kotlin/gui/config/EnumRenderer.kt
new file mode 100644
index 0000000..3b80b7e
--- /dev/null
+++ b/src/main/kotlin/gui/config/EnumRenderer.kt
@@ -0,0 +1,15 @@
+package moe.nea.firmament.gui.config
+
+import net.minecraft.text.Text
+
+interface EnumRenderer<E : Any> {
+ fun getName(option: ManagedOption<E>, value: E): Text
+
+ companion object {
+ fun <E : Enum<E>> default() = object : EnumRenderer<E> {
+ override fun getName(option: ManagedOption<E>, value: E): Text {
+ return Text.translatable(option.rawLabelText + ".choice." + value.name.lowercase())
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/gui/config/ManagedConfig.kt b/src/main/kotlin/gui/config/ManagedConfig.kt
index 8222a46..47a9c92 100644
--- a/src/main/kotlin/gui/config/ManagedConfig.kt
+++ b/src/main/kotlin/gui/config/ManagedConfig.kt
@@ -1,5 +1,6 @@
package moe.nea.firmament.gui.config
+import com.mojang.serialization.Codec
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
import io.github.notenoughupdates.moulconfig.gui.GuiContext
@@ -20,6 +21,7 @@ import kotlin.io.path.writeText
import kotlin.time.Duration
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
+import net.minecraft.util.StringIdentifiable
import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.FirmButtonComponent
import moe.nea.firmament.keybindings.SavedKeyBinding
@@ -113,6 +115,28 @@ abstract class ManagedConfig(
return option(propertyName, default, BooleanHandler(this))
}
+ protected fun <E> choice(
+ propertyName: String,
+ universe: List<E>,
+ default: () -> E
+ ): ManagedOption<E> where E : Enum<E>, E : StringIdentifiable {
+ return option(propertyName, default, ChoiceHandler(universe))
+ }
+
+// TODO: wait on https://youtrack.jetbrains.com/issue/KT-73434
+// protected inline fun <reified E> choice(
+// propertyName: String,
+// noinline default: () -> E
+// ): ManagedOption<E> where E : Enum<E>, E : StringIdentifiable {
+// return choice(
+// propertyName,
+// enumEntries<E>().toList(),
+// StringIdentifiable.createCodec { enumValues<E>() },
+// EnumRenderer.default(),
+// default
+// )
+// }
+
protected fun duration(
propertyName: String,
min: Duration,