More precise filters in textinputpanel

This commit is contained in:
DBotThePony 2023-08-10 17:36:07 +07:00
parent abe82d456c
commit 5784b3346f
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -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<out S : Screen>(
@ -179,7 +182,7 @@ open class TextInputPanel<out S : Screen>(
textCache = null
val old = oldText.joinToString("\n")
oldText = ArrayList(lines)
onTextChanged(old, textCache())
onTextChanged(textCache(), old)
}
}
@ -650,8 +653,10 @@ open class TextInputPanel<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
return true
}
open fun acceptsCharacter(codepoint: Char, mods: Int = 0): Boolean {
return true
fun interface CharacterFilter : Predicate<Char> {
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<out S : Screen>(
return true
}
if (!acceptsCharacter(codepoint, mods)) {
playGuiClickSound()
return true
}
wipeSelection()
if (!multiLine)
@ -1045,6 +1077,15 @@ open class TextInputPanel<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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