selection wiping

This commit is contained in:
DBotThePony 2023-01-26 00:17:15 +07:00
parent dac83d7e63
commit 16e371ec01
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -34,6 +34,7 @@ open class TextInputPanel<out S : Screen>(
private data class TextSelection(val start: Int, val end: Int) {
val isInversed get() = start > end
val isNotEmpty get() = start != end
val isValid get() = start != end
val actualStart get() = if (isInversed) this.end else this.start
val actualEnd get() = if (isInversed) this.start else this.end
@ -67,6 +68,14 @@ open class TextInputPanel<out S : Screen>(
}
}
private fun putSelection(index: Int, selection: TextSelection) {
if (selection.isValid) {
selections[index] = selection
} else {
selections.remove(index)
}
}
private inner class Snapshot {
private val lines = ArrayList(this@TextInputPanel.lines) // ultra fast copy
private val cursorLine = this@TextInputPanel.cursorLine
@ -296,19 +305,19 @@ open class TextInputPanel<out S : Screen>(
val (start, end) = selection
if (character < start) {
selections[line] = TextSelection(start + moveBy, end + moveBy)
putSelection(line, TextSelection(start + moveBy, end + moveBy))
} else if (character > end && character + moveBy < end) {
if (character + moveBy < start) {
// selections.remove(line)
selections[line] = TextSelection(0, 0)
} else {
selections[line] = TextSelection(start, character + moveBy)
putSelection(line, TextSelection(start, character + moveBy))
}
} else if (character in start .. end) {
if (moveBy > 0 || character + moveBy <= start) {
selections[line] = TextSelection(start, end + moveBy)
putSelection(line, TextSelection(start, end + moveBy))
} else {
selections[line] = TextSelection(character + moveBy, end + moveBy)
putSelection(line, TextSelection(character + moveBy, end + moveBy))
}
}
}
@ -319,29 +328,41 @@ open class TextInputPanel<out S : Screen>(
return
pushbackSnapshotIfNoTimer()
val set = selections.int2ObjectEntrySet()
val inversed = ArrayList(selections.int2ObjectEntrySet())
while (set.isNotEmpty()) {
val (lineNumber, selection) = set.last()
selections.remove(lineNumber)
val line = this[lineNumber] ?: continue
if (!selection.isValid) continue // ???
var downTo = inversed.size.ushr(1)
if (inversed.size and 1 == 1) downTo++
for (i in inversed.size - 1 downTo downTo) {
val i2 = inversed.size - i
val a = inversed[i]
val b = inversed[i2]
inversed[i] = b
inversed[i2] = a
}
for ((lineNumber, selection) in inversed) {
if (selection.start != selection.end) {
if (selection.start == 0 && selection.end == this[lineNumber]!!.length) {
if (selection.coversEntireLine(line)) {
removeLine(lineNumber)
} else if (selection.coversEntireString(line)) {
this[lineNumber] = ""
} else if (selection.coversNewline(line)) {
val before = line.substring(0, selection.actualStart.coerceIn(0, line.length))
val next = this[lineNumber + 1]
if (next == null) {
this[lineNumber] = before
} else {
this[lineNumber] = before + next
removeLine(lineNumber + 1)
}
} else {
val before = line.substring(0, selection.actualStart.coerceIn(0, line.length))
val after = line.substring(selection.actualEnd.coerceIn(0, line.length))
this[lineNumber] = before + after
}
if (lineNumber < cursorLine) {
cursorLine = lineNumber
cursorCharacter = selection.actualStart
} else if (lineNumber == cursorLine && cursorCharacter > selection.actualStart) {
cursorCharacter = selection.actualStart
}
}
// selections.clear()
}
protected open fun textChanged(oldText: String, newText: String) {}
@ -453,22 +474,22 @@ open class TextInputPanel<out S : Screen>(
val result = advanceCursorLeft(greedy)
if (!result.linesChanged)
selections[result.oldLine] = TextSelection(
putSelection(result.oldLine, TextSelection(
existing?.start ?: result.oldCharacter,
result.newCharacter)
result.newCharacter))
else {
this[result.newLine]?.let {
val existingNewline = selections[result.newLine]
if (existingNewline == null) {
selections[result.newLine] = TextSelection(
putSelection(result.newLine, TextSelection(
Int.MAX_VALUE,
it.length)
it.length))
} else {
if (!existingNewline.isInversed) {
selections[result.newLine] = TextSelection(
putSelection(result.newLine, TextSelection(
existingNewline.start,
result.newCharacter)
result.newCharacter))
}
}
}
@ -485,9 +506,9 @@ open class TextInputPanel<out S : Screen>(
val existing = selections[cursorLine]
val result = advanceCursorRight(greedy)
selections[result.oldLine] = TextSelection(
putSelection(result.oldLine, TextSelection(
existing?.start ?: result.oldCharacter,
if (result.couldHaveChangedLine) Int.MAX_VALUE else result.newCharacter)
if (result.couldHaveChangedLine) Int.MAX_VALUE else result.newCharacter))
}
override fun keyPressedInternal(key: Int, scancode: Int, mods: Int): Boolean {
@ -644,7 +665,10 @@ open class TextInputPanel<out S : Screen>(
}
if (key == InputConstants.KEY_BACKSPACE) {
wipeSelection()
if (selections.isNotEmpty()) {
wipeSelection()
return true
}
val line = this[cursorLine]
@ -692,7 +716,10 @@ open class TextInputPanel<out S : Screen>(
}
if (key == InputConstants.KEY_DELETE) {
wipeSelection()
if (selections.isNotEmpty()) {
wipeSelection()
return true
}
if (cursorLine !in 0 until lines.size) {
cursorLine = lines.size - 1
@ -799,7 +826,7 @@ open class TextInputPanel<out S : Screen>(
color = textColor
)
if (selection != null && (selection.isNotEmpty || selection.coversEntireLine(line))) {
if (selection != null && selection.isValid && (selection.isNotEmpty || selection.coversEntireLine(line))) {
val (before, selected) = selection.sub(line)
var x = 0f