text marking, input improvements

This commit is contained in:
Bixilon 2022-02-08 22:04:55 +01:00
parent b65cca66f4
commit d4b0e896d0
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
2 changed files with 98 additions and 30 deletions

View File

@ -14,12 +14,15 @@
package de.bixilon.minosoft.gui.rendering.gui.elements.text.mark
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ColorElement
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
import de.bixilon.minosoft.gui.rendering.gui.input.ModifierKeys
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
@ -59,8 +62,8 @@ class MarkTextElement(
}
fun mark(start: Int, end: Int) {
markStartPosition = start
markEndPosition = end
markStartPosition = minOf(start, end)
markEndPosition = maxOf(start, end)
forceSilentApply()
}
@ -75,8 +78,18 @@ class MarkTextElement(
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
if (markStartPosition >= 0) {
for (line in renderInfo.lines) {
// ToDo
val message = chatComponent.message // ToDo: This does not include formatting
val preMark = TextElement(guiRenderer, message.substring(0, markStartPosition), parent = _parent)
val mark = TextElement(guiRenderer, message.substring(markStartPosition, markEndPosition), parent = _parent)
val markOffset = Vec2i(preMark.renderInfo.lines.lastOrNull()?.width ?: 0, preMark.size.y)
if (markOffset.y > 0 && (preMark.renderInfo.lines.lastOrNull()?.width ?: 0) <= (renderInfo.lines.lastOrNull()?.width ?: 0)) {
markOffset.y -= Font.TOTAL_CHAR_HEIGHT
}
for (line in mark.renderInfo.lines) {
ColorElement(guiRenderer, size = Vec2i(line.width, Font.TOTAL_CHAR_HEIGHT), color = ChatColors.DARK_BLUE).render(offset + markOffset, consumer, options)
markOffset.x = 0
markOffset.y += Font.TOTAL_CHAR_HEIGHT
}
}
@ -95,8 +108,21 @@ class MarkTextElement(
}
mark(0, chatComponent.message.length)
}
KeyCodes.KEY_C -> {
if (controlDown) {
copy()
}
}
KeyCodes.KEY_ESCAPE -> unmark()
else -> return
}
}
fun copy() {
val markedText = markedText
if (markedText.isEmpty()) {
return
}
renderWindow.window.clipboardText = markedText
}
}

View File

@ -68,7 +68,9 @@ class TextInputElement(
override fun forceSilentApply() {
if (!textUpToDate) {
textElement._chatComponent = TextComponent(_value)
textElement.unmark()
textElement.forceSilentApply()
textUpToDate = true
}
background.size = Vec2i(prefMaxSize.x, prefMaxSize.y)
@ -96,8 +98,11 @@ class TextInputElement(
private fun insert(string: String) {
val insert = string.replace("\n", "").replace("\r", "").replace('§', '&')
if (textElement.markStartPosition > 0) {
if (textElement.marked) {
_value.delete(textElement.markStartPosition, textElement.markEndPosition)
if (pointer > textElement.markStartPosition) {
pointer = textElement.markStartPosition
}
}
val appendLength = minOf(insert.length, maxLength - _value.length)
_value.insert(pointer, insert.substring(0, appendLength))
@ -115,26 +120,42 @@ class TextInputElement(
}
private fun mark(mark: Boolean, right: Boolean) {
val marked = textElement.marked
if (mark) {
var start: Int = textElement.markStartPosition
var end: Int = textElement.markEndPosition
if (right) {
if (start < 0) {
start = pointer
end = start
if (start == pointer) {
start++
} else {
if (start < 0) {
start = pointer
end = start
}
end++
}
end++
} else {
if (start < 0) {
end = pointer
start = end
if (end == pointer) {
end--
} else {
if (start < 0) {
end = pointer
start = end
}
start--
}
start--
}
textElement.mark(start, end)
} else {
textElement.unmark()
if (right) {
pointer++
} else {
pointer--
}
return
}
pointer = if (marked) if (right) textElement.markEndPosition else textElement.markStartPosition else if (right) minOf(_value.length, pointer + 1) else maxOf(0, pointer - 1)
textElement.unmark()
}
override fun onKey(key: KeyCodes, type: KeyChangeTypes) {
@ -150,43 +171,64 @@ class TextInputElement(
insert(guiRenderer.renderWindow.window.clipboardText)
}
}
KeyCodes.KEY_C -> {
KeyCodes.KEY_X -> {
if (controlDown) {
val markedText = textElement.markedText
if (markedText.isEmpty()) {
return
}
renderWindow.window.clipboardText = markedText
textElement.copy()
insert("")
}
}
KeyCodes.KEY_BACKSPACE -> {
if (pointer == 0 || _value.isEmpty()) {
if (_value.isEmpty()) {
return
}
_value.deleteCharAt(pointer - 1)
textUpToDate = false
pointer--
if (textElement.marked) {
insert("")
} else if (pointer == 0) {
return
} else {
_value.deleteCharAt(pointer - 1)
pointer--
textUpToDate = false
}
}
KeyCodes.KEY_DELETE -> {
if (pointer == _value.length || _value.isEmpty()) {
if (_value.isEmpty()) {
return
}
_value.deleteCharAt(pointer)
textUpToDate = false
if (textElement.marked) {
insert("")
} else if (pointer == _value.length) {
return
} else {
_value.deleteCharAt(pointer)
textUpToDate = false
}
}
KeyCodes.KEY_LEFT -> {
if (pointer == 0) {
if (!shiftDown) {
textElement.unmark()
}
return
}
mark(shiftDown, false)
pointer--
}
KeyCodes.KEY_RIGHT -> {
if (pointer == _value.length) {
if (!shiftDown && pointer == _value.length) {
textElement.unmark()
}
return
}
mark(shiftDown, true)
pointer++
}
KeyCodes.KEY_HOME -> {
textElement.unmark()
pointer = 0
}
KeyCodes.KEY_END -> {
textElement.unmark()
pointer = value.length
}
else -> return textElement.onKey(key, type)
}