selection wiping
This commit is contained in:
parent
dac83d7e63
commit
16e371ec01
@ -34,6 +34,7 @@ open class TextInputPanel<out S : Screen>(
|
|||||||
private data class TextSelection(val start: Int, val end: Int) {
|
private data class TextSelection(val start: Int, val end: Int) {
|
||||||
val isInversed get() = start > end
|
val isInversed get() = start > end
|
||||||
val isNotEmpty get() = start != end
|
val isNotEmpty get() = start != end
|
||||||
|
val isValid get() = start != end
|
||||||
|
|
||||||
val actualStart get() = if (isInversed) this.end else this.start
|
val actualStart get() = if (isInversed) this.end else this.start
|
||||||
val actualEnd get() = if (isInversed) this.start else this.end
|
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 inner class Snapshot {
|
||||||
private val lines = ArrayList(this@TextInputPanel.lines) // ultra fast copy
|
private val lines = ArrayList(this@TextInputPanel.lines) // ultra fast copy
|
||||||
private val cursorLine = this@TextInputPanel.cursorLine
|
private val cursorLine = this@TextInputPanel.cursorLine
|
||||||
@ -296,19 +305,19 @@ open class TextInputPanel<out S : Screen>(
|
|||||||
val (start, end) = selection
|
val (start, end) = selection
|
||||||
|
|
||||||
if (character < start) {
|
if (character < start) {
|
||||||
selections[line] = TextSelection(start + moveBy, end + moveBy)
|
putSelection(line, TextSelection(start + moveBy, end + moveBy))
|
||||||
} else if (character > end && character + moveBy < end) {
|
} else if (character > end && character + moveBy < end) {
|
||||||
if (character + moveBy < start) {
|
if (character + moveBy < start) {
|
||||||
// selections.remove(line)
|
// selections.remove(line)
|
||||||
selections[line] = TextSelection(0, 0)
|
selections[line] = TextSelection(0, 0)
|
||||||
} else {
|
} else {
|
||||||
selections[line] = TextSelection(start, character + moveBy)
|
putSelection(line, TextSelection(start, character + moveBy))
|
||||||
}
|
}
|
||||||
} else if (character in start .. end) {
|
} else if (character in start .. end) {
|
||||||
if (moveBy > 0 || character + moveBy <= start) {
|
if (moveBy > 0 || character + moveBy <= start) {
|
||||||
selections[line] = TextSelection(start, end + moveBy)
|
putSelection(line, TextSelection(start, end + moveBy))
|
||||||
} else {
|
} 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
|
return
|
||||||
|
|
||||||
pushbackSnapshotIfNoTimer()
|
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 (selection.coversEntireLine(line)) {
|
||||||
if (inversed.size and 1 == 1) downTo++
|
removeLine(lineNumber)
|
||||||
|
} else if (selection.coversEntireString(line)) {
|
||||||
for (i in inversed.size - 1 downTo downTo) {
|
this[lineNumber] = ""
|
||||||
val i2 = inversed.size - i
|
} else if (selection.coversNewline(line)) {
|
||||||
val a = inversed[i]
|
val before = line.substring(0, selection.actualStart.coerceIn(0, line.length))
|
||||||
val b = inversed[i2]
|
val next = this[lineNumber + 1]
|
||||||
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 (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) {}
|
protected open fun textChanged(oldText: String, newText: String) {}
|
||||||
@ -453,22 +474,22 @@ open class TextInputPanel<out S : Screen>(
|
|||||||
val result = advanceCursorLeft(greedy)
|
val result = advanceCursorLeft(greedy)
|
||||||
|
|
||||||
if (!result.linesChanged)
|
if (!result.linesChanged)
|
||||||
selections[result.oldLine] = TextSelection(
|
putSelection(result.oldLine, TextSelection(
|
||||||
existing?.start ?: result.oldCharacter,
|
existing?.start ?: result.oldCharacter,
|
||||||
result.newCharacter)
|
result.newCharacter))
|
||||||
else {
|
else {
|
||||||
this[result.newLine]?.let {
|
this[result.newLine]?.let {
|
||||||
val existingNewline = selections[result.newLine]
|
val existingNewline = selections[result.newLine]
|
||||||
|
|
||||||
if (existingNewline == null) {
|
if (existingNewline == null) {
|
||||||
selections[result.newLine] = TextSelection(
|
putSelection(result.newLine, TextSelection(
|
||||||
Int.MAX_VALUE,
|
Int.MAX_VALUE,
|
||||||
it.length)
|
it.length))
|
||||||
} else {
|
} else {
|
||||||
if (!existingNewline.isInversed) {
|
if (!existingNewline.isInversed) {
|
||||||
selections[result.newLine] = TextSelection(
|
putSelection(result.newLine, TextSelection(
|
||||||
existingNewline.start,
|
existingNewline.start,
|
||||||
result.newCharacter)
|
result.newCharacter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,9 +506,9 @@ open class TextInputPanel<out S : Screen>(
|
|||||||
val existing = selections[cursorLine]
|
val existing = selections[cursorLine]
|
||||||
val result = advanceCursorRight(greedy)
|
val result = advanceCursorRight(greedy)
|
||||||
|
|
||||||
selections[result.oldLine] = TextSelection(
|
putSelection(result.oldLine, TextSelection(
|
||||||
existing?.start ?: result.oldCharacter,
|
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 {
|
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) {
|
if (key == InputConstants.KEY_BACKSPACE) {
|
||||||
wipeSelection()
|
if (selections.isNotEmpty()) {
|
||||||
|
wipeSelection()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
val line = this[cursorLine]
|
val line = this[cursorLine]
|
||||||
|
|
||||||
@ -692,7 +716,10 @@ open class TextInputPanel<out S : Screen>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key == InputConstants.KEY_DELETE) {
|
if (key == InputConstants.KEY_DELETE) {
|
||||||
wipeSelection()
|
if (selections.isNotEmpty()) {
|
||||||
|
wipeSelection()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if (cursorLine !in 0 until lines.size) {
|
if (cursorLine !in 0 until lines.size) {
|
||||||
cursorLine = lines.size - 1
|
cursorLine = lines.size - 1
|
||||||
@ -799,7 +826,7 @@ open class TextInputPanel<out S : Screen>(
|
|||||||
color = textColor
|
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)
|
val (before, selected) = selection.sub(line)
|
||||||
|
|
||||||
var x = 0f
|
var x = 0f
|
||||||
|
Loading…
Reference in New Issue
Block a user