try to fix some selection bugs
This commit is contained in:
parent
518b7e67fe
commit
9c762d50fa
@ -6,7 +6,6 @@ import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import it.unimi.dsi.fastutil.chars.Char2IntAVLTreeMap
|
||||
import it.unimi.dsi.fastutil.chars.Char2IntFunction
|
||||
import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap
|
||||
import it.unimi.dsi.fastutil.chars.CharOpenHashSet
|
||||
@ -16,7 +15,6 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
import org.joml.Vector2i
|
||||
import ru.dbotthepony.mc.otm.client.isCtrlDown
|
||||
import ru.dbotthepony.mc.otm.client.isKeyDown
|
||||
import ru.dbotthepony.mc.otm.client.isShiftDown
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
||||
@ -35,40 +33,35 @@ open class TextInputPanel<out S : Screen>(
|
||||
width: Float = 10f,
|
||||
height: Float = 10f,
|
||||
) : EditablePanel<S>(screen, parent, x, y, width, height) {
|
||||
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
|
||||
private data class TextSelection(val cursor: Int, val shift: Int) {
|
||||
val isLeft get() = shift < 0
|
||||
val isRight get() = shift > 0
|
||||
|
||||
val actualStart get() = if (isInversed) this.end else this.start
|
||||
val actualEnd get() = if (isInversed) this.start else this.end
|
||||
fun move(value: Int, lineLength: Int): TextSelection {
|
||||
return TextSelection(cursor, (shift + value).coerceIn(-cursor, lineLength - cursor + 1))
|
||||
}
|
||||
|
||||
val isValid get() = shift != 0
|
||||
val start get() = if (isRight) cursor else cursor + shift
|
||||
val end get() = if (isRight) cursor + shift else cursor
|
||||
|
||||
fun sub(line: String): Pair<String, String> {
|
||||
val before = line.substring(0, actualStart.coerceIn(0, line.length))
|
||||
val selected = line.substring(actualStart.coerceIn(0, line.length), actualEnd.coerceAtMost(line.length))
|
||||
val before = line.substring(0, start.coerceIn(0, line.length))
|
||||
val selected = line.substring(start.coerceIn(0, line.length), end.coerceAtMost(line.length))
|
||||
|
||||
return before to selected
|
||||
}
|
||||
|
||||
fun coversEntireString(value: String?): Boolean {
|
||||
if (value == null)
|
||||
return false
|
||||
|
||||
return value.length <= actualEnd && actualStart <= 0
|
||||
fun coversEntireString(value: String): Boolean {
|
||||
return start <= 0 && value.length <= end
|
||||
}
|
||||
|
||||
fun coversEntireLine(value: String?): Boolean {
|
||||
if (value == null)
|
||||
return true
|
||||
|
||||
return value.length < actualEnd && actualStart <= 0
|
||||
fun coversEntireLine(value: String): Boolean {
|
||||
return start <= 0 && value.length < end
|
||||
}
|
||||
|
||||
fun coversNewline(value: String?): Boolean {
|
||||
if (value == null)
|
||||
return actualEnd == Int.MAX_VALUE
|
||||
|
||||
return value.length < actualEnd
|
||||
fun coversNewline(value: String): Boolean {
|
||||
return value.length < end
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,7 +299,8 @@ open class TextInputPanel<out S : Screen>(
|
||||
val selection = selections[line]
|
||||
|
||||
if (selection != null) {
|
||||
val (start, end) = selection
|
||||
val start = selection.start
|
||||
val end = selection.end
|
||||
|
||||
if (character < start) {
|
||||
putSelection(line, TextSelection(start + moveBy, end + moveBy))
|
||||
@ -345,7 +339,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
} else if (selection.coversEntireString(line)) {
|
||||
this[lineNumber] = ""
|
||||
} else if (selection.coversNewline(line)) {
|
||||
val before = line.substring(0, selection.actualStart.coerceIn(0, line.length))
|
||||
val before = line.substring(0, selection.start.coerceIn(0, line.length))
|
||||
val next = this[lineNumber + 1]
|
||||
|
||||
if (next == null) {
|
||||
@ -355,22 +349,20 @@ open class TextInputPanel<out S : Screen>(
|
||||
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))
|
||||
val before = line.substring(0, selection.start.coerceIn(0, line.length))
|
||||
val after = line.substring(selection.end.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
|
||||
cursorCharacter = selection.start
|
||||
} else if (lineNumber == cursorLine && cursorCharacter > selection.start) {
|
||||
cursorCharacter = selection.start
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun textChanged(oldText: String, newText: String) {}
|
||||
|
||||
var text: String
|
||||
get() {
|
||||
var textCache = textCache
|
||||
@ -410,14 +402,17 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
fun advanceCursorLeft(greedy: Boolean = false): CursorAdvanceResult {
|
||||
val oldLine = cursorLine
|
||||
val oldChar = cursorCharacter
|
||||
val line = this[cursorLine]
|
||||
var couldHaveChangedLine = false
|
||||
|
||||
if (line != null && cursorCharacter > line.length) {
|
||||
cursorCharacter = line.length - 1
|
||||
cursorCharacter = line.length
|
||||
} else if (cursorCharacter < 0) {
|
||||
cursorCharacter = 0
|
||||
}
|
||||
|
||||
val oldChar = cursorCharacter
|
||||
|
||||
if (cursorCharacter > 0) {
|
||||
if (greedy && line != null) {
|
||||
cursorCharacter = greedyAdvanceLeft(line, cursorCharacter)
|
||||
@ -444,11 +439,18 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
fun advanceCursorRight(greedy: Boolean = false): CursorAdvanceResult {
|
||||
val oldLine = cursorLine
|
||||
val oldChar = cursorCharacter
|
||||
var couldHaveChangedLine = false
|
||||
|
||||
val line = this[cursorLine]
|
||||
|
||||
if (line != null && cursorCharacter > line.length) {
|
||||
cursorCharacter = line.length
|
||||
} else if (cursorCharacter < 0) {
|
||||
cursorCharacter = 0
|
||||
}
|
||||
|
||||
val oldChar = cursorCharacter
|
||||
|
||||
if (greedy && line != null && cursorCharacter + 1 < line.length) {
|
||||
cursorCharacter = greedyAdvanceRight(line, cursorCharacter)
|
||||
} else {
|
||||
@ -472,47 +474,39 @@ open class TextInputPanel<out S : Screen>(
|
||||
}
|
||||
|
||||
private fun simulateSelectLeft(greedy: Boolean) {
|
||||
val thisLine = this[cursorLine] ?: return
|
||||
|
||||
val existing = selections[cursorLine]
|
||||
val line = this[cursorLine] ?: return
|
||||
val existing = selections[cursorLine] ?: TextSelection(cursorCharacter, 0)
|
||||
val result = advanceCursorLeft(greedy)
|
||||
|
||||
if (!result.linesChanged)
|
||||
putSelection(result.oldLine, TextSelection(
|
||||
existing?.start ?: result.oldCharacter,
|
||||
result.newCharacter))
|
||||
else {
|
||||
this[result.newLine]?.let {
|
||||
val existingNewline = selections[result.newLine]
|
||||
|
||||
if (existingNewline == null) {
|
||||
putSelection(result.newLine, TextSelection(
|
||||
Int.MAX_VALUE,
|
||||
it.length))
|
||||
if (result.couldHaveChangedLine) {
|
||||
putSelection(result.oldLine, existing.move(-line.length, line.length))
|
||||
} else {
|
||||
if (!existingNewline.isInversed) {
|
||||
putSelection(result.newLine, TextSelection(
|
||||
existingNewline.start,
|
||||
result.newCharacter))
|
||||
}
|
||||
}
|
||||
putSelection(result.oldLine, existing.move(result.newCharacter - result.oldCharacter, line.length))
|
||||
}
|
||||
|
||||
if (existing != null && existing.actualStart == 0 && thisLine.isEmpty() && !existing.isInversed) {
|
||||
selections.remove(result.oldLine)
|
||||
if (result.linesChanged) {
|
||||
val existingNew = selections[result.newLine]
|
||||
val lineNew = this[result.newLine] ?: return
|
||||
|
||||
if (existingNew == null) {
|
||||
putSelection(result.newLine, TextSelection(result.newCharacter + 1, -1))
|
||||
} else {
|
||||
putSelection(result.newLine, existingNew.move(-1, lineNew.length))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun simulateSelectRight(greedy: Boolean) {
|
||||
this[cursorLine] ?: return
|
||||
|
||||
val existing = selections[cursorLine]
|
||||
val line = this[cursorLine] ?: return
|
||||
val existing = selections[cursorLine] ?: TextSelection(cursorCharacter, 0)
|
||||
val result = advanceCursorRight(greedy)
|
||||
|
||||
putSelection(result.oldLine, TextSelection(
|
||||
existing?.start ?: result.oldCharacter,
|
||||
if (result.couldHaveChangedLine) Int.MAX_VALUE else result.newCharacter))
|
||||
if (result.couldHaveChangedLine) {
|
||||
if (result.oldLine != lines.size - 1)
|
||||
putSelection(result.oldLine, existing.move(line.length.coerceAtLeast(1), line.length))
|
||||
} else {
|
||||
putSelection(result.oldLine, existing.move(result.newCharacter - result.oldCharacter, line.length))
|
||||
}
|
||||
}
|
||||
|
||||
private fun simulateSelectionUp(): Boolean {
|
||||
@ -559,6 +553,13 @@ open class TextInputPanel<out S : Screen>(
|
||||
while (this.cursorCharacter < cursorCharacter) {
|
||||
simulateSelectRight(false)
|
||||
}
|
||||
} else {
|
||||
if (line.isEmpty()) {
|
||||
val existing = selections[this.cursorLine]
|
||||
|
||||
if (existing != null && existing.isLeft) {
|
||||
selections.remove(this.cursorLine)
|
||||
}
|
||||
} else {
|
||||
val store = this.cursorLine
|
||||
|
||||
@ -568,6 +569,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
|
||||
this.cursorLine = store
|
||||
}
|
||||
}
|
||||
|
||||
this.cursorCharacter = cursorCharacter
|
||||
return true
|
||||
@ -842,7 +844,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
color = textColor
|
||||
)
|
||||
|
||||
if (selection != null && selection.isValid && (selection.isNotEmpty || selection.coversEntireLine(line))) {
|
||||
if (selection != null && selection.isValid) {
|
||||
val (before, selected) = selection.sub(line)
|
||||
|
||||
var x = 0f
|
||||
@ -851,7 +853,7 @@ open class TextInputPanel<out S : Screen>(
|
||||
x = font.width(before).toFloat()
|
||||
}
|
||||
|
||||
val width = if (selection.coversNewline(line)) this.width - x else font.width(selected).toFloat()
|
||||
val width = if (selection.coversNewline(line) && i != lines.size - 1) this.width - x else font.width(selected).toFloat()
|
||||
|
||||
RenderSystem.setShader(GameRenderer::getPositionShader)
|
||||
RenderSystem.setShaderColor(0.0f, 0.0f, 1.0f, 1.0f)
|
||||
|
Loading…
Reference in New Issue
Block a user