From 5784b3346fa327ff34ea5dbc00d4d69b5efba893 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 10 Aug 2023 17:36:07 +0700 Subject: [PATCH] More precise filters in textinputpanel --- .../screen/panels/input/TextInputPanel.kt | 86 +++++++++++++++---- 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt index ad74f87d4..c88a4eec4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt @@ -27,8 +27,11 @@ import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.addAll +import ru.dbotthepony.mc.otm.core.collect.mapToInt +import ru.dbotthepony.mc.otm.core.collect.reduce import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.milliTime +import java.util.function.Predicate import kotlin.math.roundToInt open class TextInputPanel( @@ -179,7 +182,7 @@ open class TextInputPanel( textCache = null val old = oldText.joinToString("\n") oldText = ArrayList(lines) - onTextChanged(old, textCache()) + onTextChanged(textCache(), old) } } @@ -650,8 +653,10 @@ open class TextInputPanel( return true } - open fun onEnter() { + var onEnter: Runnable? = null + open fun onEnter() { + onEnter?.run() } override fun keyPressedInternal(key: Int, scancode: Int, mods: Int): Boolean { @@ -899,7 +904,8 @@ open class TextInputPanel( pushbackSnapshot() if (multiLine) { - val insert = minecraft.keyboardHandler.clipboard.replace("\t", " ").filter { acceptsCharacter(it) }.split(NEWLINES).toMutableList() + var index = cursorRow + (0 until cursorLine).iterator().mapToInt { this[it]?.length ?: 0 }.reduce(0, Int::plus) + val insert = minecraft.keyboardHandler.clipboard.replace("\t", " ").filter { acceptsCharacter(it, 0, index++) }.split(NEWLINES).toMutableList() val actualLastSize = insert.lastOrNull()?.length ?: 0 val line = this[cursorLine] @@ -938,7 +944,8 @@ open class TextInputPanel( cursorRow = actualLastSize } } else { - val insert = minecraft.keyboardHandler.clipboard.replace("\t", " ").replace(NEWLINES, "").filter { acceptsCharacter(it) } + var index = cursorRow + (0 until cursorLine).iterator().mapToInt { this[it]?.length ?: 0 }.reduce(0, Int::plus) + val insert = minecraft.keyboardHandler.clipboard.replace("\t", " ").replace(NEWLINES, "").filter { acceptsCharacter(it, 0, index++) } val line = this[cursorLine] if (line == null) { @@ -1017,8 +1024,38 @@ open class TextInputPanel( return true } - open fun acceptsCharacter(codepoint: Char, mods: Int = 0): Boolean { - return true + fun interface CharacterFilter : Predicate { + fun acceptsCharacter(codepoint: Char, mods: Int, index: Int): Boolean + + override fun test(t: Char): Boolean { + return acceptsCharacter(t, 0, 0) + } + } + + var characterFilter: CharacterFilter? = null + + fun allowEverything() { + characterFilter = null + } + + fun allowNumbersAndSign() { + characterFilter = CharacterFilter { it, _, i -> if (i == 0) it in SIGNS || it in NUMBERS else it in NUMBERS } + } + + fun allowNumbers() { + characterFilter = CharacterFilter { it, _, _ -> it in NUMBERS } + } + + fun allowHexNumbersAndSign() { + characterFilter = CharacterFilter { it, _, i -> if (i == 0) it in SIGNS || it in HEX else it in HEX } + } + + fun allowHexNumbers() { + characterFilter = CharacterFilter { it, _, _ -> it in HEX } + } + + open fun acceptsCharacter(codepoint: Char, mods: Int = 0, index: Int): Boolean { + return characterFilter?.acceptsCharacter(codepoint, mods, index) ?: true } override fun charTypedInternal(codepoint: Char, mods: Int): Boolean { @@ -1027,11 +1064,6 @@ open class TextInputPanel( return true } - if (!acceptsCharacter(codepoint, mods)) { - playGuiClickSound() - return true - } - wipeSelection() if (!multiLine) @@ -1045,6 +1077,15 @@ open class TextInputPanel( cursorRow = 0 } + var index = 0 + for (i in 0 until cursorLine) index += this[i]?.length ?: 0 + index += cursorRow + + if (!acceptsCharacter(codepoint, mods, index)) { + playGuiClickSound() + return true + } + if (cursorRow >= line.length) line += codepoint else @@ -1349,13 +1390,13 @@ open class TextInputPanel( return true } - protected open fun onTextChanged(old: String, new: String) { - changeCallback?.invoke(old, new) + protected open fun onTextChanged(new: String, old: String) { + changeCallback?.invoke(new, old) } - protected var changeCallback: ((old: String, new: String) -> Unit)? = null + protected var changeCallback: ((new: String, old: String) -> Unit)? = null - fun onTextChange(callback: (old: String, new: String) -> Unit) { + fun onTextChange(callback: (new: String, old: String) -> Unit) { changeCallback = callback } @@ -1420,6 +1461,21 @@ open class TextInputPanel( it.add(char) } + private val NUMBERS = CharOpenHashSet().also { + for (char in "0123456789-+") + it.add(char) + } + + private val SIGNS = CharOpenHashSet().also { + for (char in "-+") + it.add(char) + } + + private val HEX = CharOpenHashSet().also { + for (char in "0123456789ABCDEFabcdef") + it.add(char) + } + private fun greedyAdvanceLeft(input: String, position: Int): Int { if (position <= 1) return -1