mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 03:44:54 -04:00
input element: improve some things, chat: don't allow spaces at the beginning
This commit is contained in:
parent
38d018e9f5
commit
54a70e6665
@ -36,24 +36,27 @@ class TextInputElement(
|
|||||||
val maxLength: Int = Int.MAX_VALUE,
|
val maxLength: Int = Int.MAX_VALUE,
|
||||||
val cursorStyles: TextCursorStyles = TextCursorStyles.CLICKED,
|
val cursorStyles: TextCursorStyles = TextCursorStyles.CLICKED,
|
||||||
var editable: Boolean = true,
|
var editable: Boolean = true,
|
||||||
|
var onChange: () -> Unit = {},
|
||||||
) : Element(guiRenderer) {
|
) : Element(guiRenderer) {
|
||||||
private val cursor = ColorElement(guiRenderer, size = Vec2i(1, Font.TOTAL_CHAR_HEIGHT))
|
private val cursor = ColorElement(guiRenderer, size = Vec2i(1, Font.TOTAL_CHAR_HEIGHT))
|
||||||
private val textElement = MarkTextElement(guiRenderer, "", background = false, parent = this)
|
private val textElement = MarkTextElement(guiRenderer, "", background = false, parent = this)
|
||||||
private val background = ColorElement(guiRenderer, Vec2i.EMPTY, RenderConstants.TEXT_BACKGROUND_COLOR)
|
private val background = ColorElement(guiRenderer, Vec2i.EMPTY, RenderConstants.TEXT_BACKGROUND_COLOR)
|
||||||
private var cursorOffset: Vec2i = Vec2i.EMPTY
|
private var cursorOffset: Vec2i = Vec2i.EMPTY
|
||||||
private val _value = StringBuffer(256)
|
val _value = StringBuffer(256)
|
||||||
var value: String
|
var value: String
|
||||||
get() = _value.toString()
|
get() = _value.toString()
|
||||||
set(value) {
|
set(value) {
|
||||||
pointer = 0
|
_pointer = 0
|
||||||
if (_value.equals(value)) {
|
if (_value.equals(value)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_value.replace(0, _value.length, value)
|
_value.replace(0, _value.length, value)
|
||||||
|
onChange()
|
||||||
|
textUpToDate = false
|
||||||
forceApply()
|
forceApply()
|
||||||
}
|
}
|
||||||
private var textUpToDate = false
|
private var textUpToDate = false
|
||||||
private var pointer = 0
|
var _pointer = 0
|
||||||
private var cursorTick = 0
|
private var cursorTick = 0
|
||||||
|
|
||||||
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
@ -75,13 +78,13 @@ class TextInputElement(
|
|||||||
}
|
}
|
||||||
background.size = Vec2i(prefMaxSize.x, prefMaxSize.y)
|
background.size = Vec2i(prefMaxSize.x, prefMaxSize.y)
|
||||||
|
|
||||||
cursorOffset = if (pointer == 0) {
|
cursorOffset = if (_pointer == 0) {
|
||||||
Vec2i.EMPTY
|
Vec2i.EMPTY
|
||||||
} else {
|
} else {
|
||||||
val preCursorText = if (pointer == value.length) {
|
val preCursorText = if (_pointer == value.length) {
|
||||||
textElement
|
textElement
|
||||||
} else {
|
} else {
|
||||||
TextElement(guiRenderer, value.substring(0, pointer), parent = this)
|
TextElement(guiRenderer, value.substring(0, _pointer), parent = this)
|
||||||
}
|
}
|
||||||
Vec2i(preCursorText.renderInfo.lines.lastOrNull()?.width ?: 0, maxOf(preCursorText.renderInfo.lines.size - 1, 0) * preCursorText.charHeight)
|
Vec2i(preCursorText.renderInfo.lines.lastOrNull()?.width ?: 0, maxOf(preCursorText.renderInfo.lines.size - 1, 0) * preCursorText.charHeight)
|
||||||
}
|
}
|
||||||
@ -104,14 +107,15 @@ class TextInputElement(
|
|||||||
val insert = string.replace("\n", "").replace("\r", "").replace('§', '&')
|
val insert = string.replace("\n", "").replace("\r", "").replace('§', '&')
|
||||||
if (textElement.marked) {
|
if (textElement.marked) {
|
||||||
_value.delete(textElement.markStartPosition, textElement.markEndPosition)
|
_value.delete(textElement.markStartPosition, textElement.markEndPosition)
|
||||||
if (pointer > textElement.markStartPosition) {
|
if (_pointer > textElement.markStartPosition) {
|
||||||
pointer = textElement.markStartPosition
|
_pointer = textElement.markStartPosition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val appendLength = minOf(insert.length, maxLength - _value.length)
|
val appendLength = minOf(insert.length, maxLength - _value.length)
|
||||||
_value.insert(pointer, insert.substring(0, appendLength))
|
_value.insert(_pointer, insert.substring(0, appendLength))
|
||||||
pointer += appendLength
|
_pointer += appendLength
|
||||||
textUpToDate = false
|
textUpToDate = false
|
||||||
|
onChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCharPress(char: Int) {
|
override fun onCharPress(char: Int) {
|
||||||
@ -132,32 +136,32 @@ class TextInputElement(
|
|||||||
var start: Int = textElement.markStartPosition
|
var start: Int = textElement.markStartPosition
|
||||||
var end: Int = textElement.markEndPosition
|
var end: Int = textElement.markEndPosition
|
||||||
if (right) {
|
if (right) {
|
||||||
if (start == pointer) {
|
if (start == _pointer) {
|
||||||
start += modify
|
start += modify
|
||||||
} else {
|
} else {
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = pointer
|
start = _pointer
|
||||||
end = start
|
end = start
|
||||||
}
|
}
|
||||||
end += modify
|
end += modify
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (end == pointer) {
|
if (end == _pointer) {
|
||||||
end += modify
|
end += modify
|
||||||
} else {
|
} else {
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
end = pointer
|
end = _pointer
|
||||||
start = end
|
start = end
|
||||||
}
|
}
|
||||||
start += modify
|
start += modify
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
textElement.mark(start, end)
|
textElement.mark(start, end)
|
||||||
pointer += modify
|
_pointer += modify
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer = if (marked) if (right) textElement.markEndPosition else textElement.markStartPosition else if (right) minOf(_value.length, pointer + modify) else maxOf(0, pointer + modify)
|
_pointer = if (marked) if (right) textElement.markEndPosition else textElement.markStartPosition else if (right) minOf(_value.length, _pointer + modify) else maxOf(0, _pointer + modify)
|
||||||
textElement.unmark()
|
textElement.unmark()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,12 +190,12 @@ class TextInputElement(
|
|||||||
}
|
}
|
||||||
if (textElement.marked) {
|
if (textElement.marked) {
|
||||||
insert("")
|
insert("")
|
||||||
} else if (pointer == 0) {
|
} else if (_pointer == 0) {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
val delete = if (controlDown) calculateWordPointer(false) else -1
|
val delete = if (controlDown) calculateWordPointer(false) else -1
|
||||||
_value.delete(pointer + delete, pointer)
|
_value.delete(_pointer + delete, _pointer)
|
||||||
pointer += delete
|
_pointer += delete
|
||||||
textUpToDate = false
|
textUpToDate = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,16 +205,16 @@ class TextInputElement(
|
|||||||
}
|
}
|
||||||
if (textElement.marked) {
|
if (textElement.marked) {
|
||||||
insert("")
|
insert("")
|
||||||
} else if (pointer == _value.length) {
|
} else if (_pointer == _value.length) {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
val delete = if (controlDown) calculateWordPointer(true) else 1
|
val delete = if (controlDown) calculateWordPointer(true) else 1
|
||||||
_value.delete(pointer, pointer + delete)
|
_value.delete(_pointer, _pointer + delete)
|
||||||
textUpToDate = false
|
textUpToDate = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCodes.KEY_LEFT -> {
|
KeyCodes.KEY_LEFT -> {
|
||||||
if (pointer == 0) {
|
if (_pointer == 0) {
|
||||||
if (!shiftDown) {
|
if (!shiftDown) {
|
||||||
textElement.unmark()
|
textElement.unmark()
|
||||||
}
|
}
|
||||||
@ -224,8 +228,8 @@ class TextInputElement(
|
|||||||
mark(shiftDown, false, modify)
|
mark(shiftDown, false, modify)
|
||||||
}
|
}
|
||||||
KeyCodes.KEY_RIGHT -> {
|
KeyCodes.KEY_RIGHT -> {
|
||||||
if (pointer == _value.length) {
|
if (_pointer == _value.length) {
|
||||||
if (!shiftDown && pointer == _value.length) {
|
if (!shiftDown && _pointer == _value.length) {
|
||||||
textElement.unmark()
|
textElement.unmark()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -240,11 +244,11 @@ class TextInputElement(
|
|||||||
}
|
}
|
||||||
KeyCodes.KEY_HOME -> {
|
KeyCodes.KEY_HOME -> {
|
||||||
textElement.unmark()
|
textElement.unmark()
|
||||||
pointer = 0
|
_pointer = 0
|
||||||
}
|
}
|
||||||
KeyCodes.KEY_END -> {
|
KeyCodes.KEY_END -> {
|
||||||
textElement.unmark()
|
textElement.unmark()
|
||||||
pointer = value.length
|
_pointer = value.length
|
||||||
}
|
}
|
||||||
else -> return textElement.onKey(key, type)
|
else -> return textElement.onKey(key, type)
|
||||||
}
|
}
|
||||||
@ -257,8 +261,8 @@ class TextInputElement(
|
|||||||
|
|
||||||
private fun calculateWordPointer(right: Boolean): Int {
|
private fun calculateWordPointer(right: Boolean): Int {
|
||||||
var modify = if (right) 1 else -1
|
var modify = if (right) 1 else -1
|
||||||
while (pointer + modify in 1 until _value.length) {
|
while (_pointer + modify in 1 until _value.length) {
|
||||||
val char = _value[pointer + modify]
|
val char = _value[_pointer + modify]
|
||||||
if (char in WORD_SEPARATORS) {
|
if (char in WORD_SEPARATORS) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -272,6 +276,10 @@ class TextInputElement(
|
|||||||
return modify
|
return modify
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onOpen() {
|
||||||
|
cursorTick = 19 // make cursor visible
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val CURSOR_TICK_ON_ACTION = 10
|
private const val CURSOR_TICK_ON_ACTION = 10
|
||||||
private val WORD_SEPARATORS = CharOpenHashSet(charArrayOf(' ', ',', ';', '-', '\'', '`', '"', '“', '„', '.', '&', '@', '^', '/', '\\', '…', '*', '⁂', '=', '?', '!', '‽', '¡', '¿', '⸮', '#', '№', '%', '‰', '‱', '°', '⌀', '+', '−', '×', '÷', '~', '±', '∓', '–', '⁀', '|', '¦', '‖', '•', '·', '©', '©', '℗', '®', '‘', '’', '“', '”', '"', '"', '‹', '›', '«', '»', '(', ')', '[', ']', '{', '}', '⟨', '⟩', '”', '〃', '†', '‡', '❧', '☞', '◊', '¶', '⸿', '፠', '๛', '※', '§'))
|
private val WORD_SEPARATORS = CharOpenHashSet(charArrayOf(' ', ',', ';', '-', '\'', '`', '"', '“', '„', '.', '&', '@', '^', '/', '\\', '…', '*', '⁂', '=', '?', '!', '‽', '¡', '¿', '⸮', '#', '№', '%', '‰', '‱', '°', '⌀', '+', '−', '×', '÷', '~', '±', '∓', '–', '⁀', '|', '¦', '‖', '•', '·', '©', '©', '℗', '®', '‘', '’', '“', '”', '"', '"', '‹', '›', '«', '»', '(', ')', '[', ']', '{', '}', '⟨', '⟩', '”', '〃', '†', '‡', '❧', '☞', '◊', '¶', '⸿', '፠', '๛', '※', '§'))
|
||||||
|
@ -69,6 +69,12 @@ class ChatElement(guiRenderer: GUIRenderer) : Element(guiRenderer), LayoutedElem
|
|||||||
chatProfile::width.profileWatchRendering(this, profile = profile) { messages.prefMaxSize = Vec2i(it, messages.prefMaxSize.y) }
|
chatProfile::width.profileWatchRendering(this, profile = profile) { messages.prefMaxSize = Vec2i(it, messages.prefMaxSize.y) }
|
||||||
chatProfile::height.profileWatchRendering(this, profile = profile) { messages.prefMaxSize = Vec2i(messages.prefMaxSize.x, it) }
|
chatProfile::height.profileWatchRendering(this, profile = profile) { messages.prefMaxSize = Vec2i(messages.prefMaxSize.x, it) }
|
||||||
forceSilentApply()
|
forceSilentApply()
|
||||||
|
input.onChange = {
|
||||||
|
while (input._value.startsWith(' ')) {
|
||||||
|
input._value.deleteCharAt(0)
|
||||||
|
input._pointer--
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -115,6 +121,7 @@ class ChatElement(guiRenderer: GUIRenderer) : Element(guiRenderer), LayoutedElem
|
|||||||
|
|
||||||
override fun onOpen() {
|
override fun onOpen() {
|
||||||
active = true
|
active = true
|
||||||
|
input.onOpen()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClose() {
|
override fun onClose() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user