mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 10:04:05 +09:00
multiple candidates display for IME
This commit is contained in:
@@ -684,7 +684,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
println("listing savegames...")
|
println("listing savegames...")
|
||||||
|
|
||||||
// create list of worlds
|
// create list of worlds
|
||||||
(File(App.worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.map { file ->
|
(File(worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
||||||
try {
|
try {
|
||||||
DiskSkimmer(file, Common.CHARSET, true)
|
DiskSkimmer(file, Common.CHARSET, true)
|
||||||
}
|
}
|
||||||
@@ -693,7 +693,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}.filter { it != null }.sortedByDescending { it!!.getLastModifiedOfFirstFile() } as List<DiskSkimmer>).forEach {
|
}.sortedByDescending { it.getLastModifiedOfFirstFile() }).forEach {
|
||||||
println(it.diskFile.absolutePath)
|
println(it.diskFile.absolutePath)
|
||||||
it.rebuild() // disk skimmer was created without initialisation, so do it now
|
it.rebuild() // disk skimmer was created without initialisation, so do it now
|
||||||
|
|
||||||
@@ -707,7 +707,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
|
|
||||||
|
|
||||||
// create list of players
|
// create list of players
|
||||||
(File(App.playersDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.map { file ->
|
(File(playersDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
||||||
try {
|
try {
|
||||||
DiskSkimmer(file, Common.CHARSET, true)
|
DiskSkimmer(file, Common.CHARSET, true)
|
||||||
}
|
}
|
||||||
@@ -716,7 +716,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}.filter { it != null }.sortedByDescending { it!!.getLastModifiedOfFirstFile() } as List<DiskSkimmer>).forEach {
|
}.sortedByDescending { it.getLastModifiedOfFirstFile() }).forEach {
|
||||||
println(it.diskFile.absolutePath)
|
println(it.diskFile.absolutePath)
|
||||||
it.rebuild() // disk skimmer was created without initialisation, so do it now
|
it.rebuild() // disk skimmer was created without initialisation, so do it now
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ object CommandDict {
|
|||||||
printdbg(this, ModMgr.loadOrder.reversed())
|
printdbg(this, ModMgr.loadOrder.reversed())
|
||||||
printdbg(this, ModMgr.loadOrder.reversed().map { ModMgr.moduleInfo[it]?.packageName })
|
printdbg(this, ModMgr.loadOrder.reversed().map { ModMgr.moduleInfo[it]?.packageName })
|
||||||
|
|
||||||
(listOf("net.torvald.terrarum") + ModMgr.loadOrder.reversed().map { ModMgr.moduleInfo[it]?.packageName }.filter { it != null }).forEach{ packageRoot ->
|
(listOf("net.torvald.terrarum") + ModMgr.loadOrder.reversed().mapNotNull { ModMgr.moduleInfo[it]?.packageName }).forEach{ packageRoot ->
|
||||||
printdbg(this, packageRoot)
|
printdbg(this, packageRoot)
|
||||||
val packageConsole = "$packageRoot.console"
|
val packageConsole = "$packageRoot.console"
|
||||||
val stream = ClassLoader.getSystemClassLoader().getResourceAsStream(packageConsole.replace('.','/'))
|
val stream = ClassLoader.getSystemClassLoader().getResourceAsStream(packageConsole.replace('.','/'))
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package net.torvald.terrarum.gamecontroller
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
typealias IMECanditates = List<String>
|
||||||
|
typealias IMEOutput = String
|
||||||
|
|
||||||
data class TerrarumKeyLayout(
|
data class TerrarumKeyLayout(
|
||||||
val name: String,
|
val name: String,
|
||||||
val symbols: Array<Array<String?>>?
|
val symbols: Array<Array<String?>>?
|
||||||
@@ -11,9 +14,9 @@ data class TerrarumKeyLayout(
|
|||||||
data class TerrarumInputMethod(
|
data class TerrarumInputMethod(
|
||||||
val name: String,
|
val name: String,
|
||||||
// (headkey, shiftin, altgrin)
|
// (headkey, shiftin, altgrin)
|
||||||
val acceptChar: (Int, Boolean, Boolean) -> Pair<String, String>, // Pair<Display Char, Output Char if any>
|
val acceptChar: (Int, Boolean, Boolean) -> Pair<IMECanditates, IMEOutput>,
|
||||||
val backspace: () -> String,
|
val backspace: () -> IMECanditates,
|
||||||
val endCompose: () -> String,
|
val endCompose: () -> IMEOutput,
|
||||||
val reset: () -> Unit,
|
val reset: () -> Unit,
|
||||||
val composing: () -> Boolean
|
val composing: () -> Boolean
|
||||||
)
|
)
|
||||||
@@ -103,6 +106,9 @@ object IME {
|
|||||||
return TerrarumKeyLayout(name, out)
|
return TerrarumKeyLayout(name, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.toCanditates(): List<String> =
|
||||||
|
this.split(',').mapNotNull { it.ifBlank { null } }
|
||||||
|
|
||||||
private fun parseImeFile(file: File): TerrarumInputMethod {
|
private fun parseImeFile(file: File): TerrarumInputMethod {
|
||||||
val code = file.readText(Charsets.UTF_8)
|
val code = file.readText(Charsets.UTF_8)
|
||||||
val jsval = context.eval("js", "\"use strict\";(function(){$code})()")
|
val jsval = context.eval("js", "\"use strict\";(function(){$code})()")
|
||||||
@@ -111,9 +117,9 @@ object IME {
|
|||||||
|
|
||||||
return TerrarumInputMethod(name, { headkey, shifted, alted ->
|
return TerrarumInputMethod(name, { headkey, shifted, alted ->
|
||||||
val a = jsval.invokeMember("accept", headkey, shifted, alted)
|
val a = jsval.invokeMember("accept", headkey, shifted, alted)
|
||||||
a.getArrayElement(0).asString() to a.getArrayElement(1).asString()
|
a.getArrayElement(0).asString().toCanditates() to a.getArrayElement(1).asString()
|
||||||
}, {
|
}, {
|
||||||
jsval.invokeMember("backspace").asString()
|
jsval.invokeMember("backspace").asString().toCanditates()
|
||||||
}, {
|
}, {
|
||||||
jsval.invokeMember("end").asString()
|
jsval.invokeMember("end").asString()
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class UIItemTextLineInput(
|
|||||||
get() = buttonsShown > 0 && relativeMouseX in btn2PosX - posX until btn2PosX - posX + WIDTH_ONEBUTTON && relativeMouseY in 0 until height
|
get() = buttonsShown > 0 && relativeMouseX in btn2PosX - posX until btn2PosX - posX + WIDTH_ONEBUTTON && relativeMouseY in 0 until height
|
||||||
|
|
||||||
private var imeOn = false
|
private var imeOn = false
|
||||||
private var composingView = CodepointSequence()
|
private var candidates: List<CodepointSequence> = listOf()
|
||||||
|
|
||||||
private fun getIME(): TerrarumInputMethod? {
|
private fun getIME(): TerrarumInputMethod? {
|
||||||
if (!imeOn) return null
|
if (!imeOn) return null
|
||||||
@@ -176,7 +176,7 @@ class UIItemTextLineInput(
|
|||||||
}
|
}
|
||||||
else if (keycodes.contains(Input.Keys.BACKSPACE)) {
|
else if (keycodes.contains(Input.Keys.BACKSPACE)) {
|
||||||
if (ime != null && ime.composing()) {
|
if (ime != null && ime.composing()) {
|
||||||
composingView = CodepointSequence(ime.backspace().toCodePoints())
|
candidates = ime.backspace().map { CodepointSequence(it.toCodePoints()) }
|
||||||
}
|
}
|
||||||
else if (cursorX <= 0) {
|
else if (cursorX <= 0) {
|
||||||
cursorX = 0
|
cursorX = 0
|
||||||
@@ -230,7 +230,7 @@ class UIItemTextLineInput(
|
|||||||
|
|
||||||
val codepoints = if (ime != null) {
|
val codepoints = if (ime != null) {
|
||||||
val newStatus = ime.acceptChar(headkey, shiftin, altgrin)
|
val newStatus = ime.acceptChar(headkey, shiftin, altgrin)
|
||||||
composingView = CodepointSequence(newStatus.first.toCodePoints())
|
candidates = newStatus.first.map { CodepointSequence(it.toCodePoints()) }
|
||||||
|
|
||||||
newStatus.second.toCodePoints()
|
newStatus.second.toCodePoints()
|
||||||
}
|
}
|
||||||
@@ -291,7 +291,7 @@ class UIItemTextLineInput(
|
|||||||
paste(s.toCodePoints())
|
paste(s.toCodePoints())
|
||||||
}
|
}
|
||||||
fboUpdateLatch = true
|
fboUpdateLatch = true
|
||||||
composingView = CodepointSequence()
|
candidates = listOf()
|
||||||
// resetIME() // not needed; IME will reset itself
|
// resetIME() // not needed; IME will reset itself
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ class UIItemTextLineInput(
|
|||||||
|
|
||||||
private fun resetIME() {
|
private fun resetIME() {
|
||||||
getIME()?.reset?.invoke()
|
getIME()?.reset?.invoke()
|
||||||
composingView = CodepointSequence()
|
candidates = listOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun paste(codepoints: List<Int>) {
|
private fun paste(codepoints: List<Int>) {
|
||||||
@@ -432,17 +432,25 @@ class UIItemTextLineInput(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// compose view background
|
// draw candidates view
|
||||||
if (composingView.size > 0) {
|
if (candidates.isNotEmpty()) {
|
||||||
val previewTextWidth = App.fontGame.getWidth(composingView)
|
val textWidths = candidates.map { App.fontGame.getWidth(CodepointSequence(it)) }
|
||||||
val previewWindowWidth = previewTextWidth.coerceAtLeast(20)
|
|
||||||
|
val candidateWinW = (textWidths.maxOrNull() ?: 0).coerceAtLeast(20)
|
||||||
|
val candidateWinH = App.fontGame.lineHeight.toInt() * candidates.size
|
||||||
|
|
||||||
|
// candidate view background
|
||||||
batch.color = TEXTINPUT_COL_BACKGROUND
|
batch.color = TEXTINPUT_COL_BACKGROUND
|
||||||
Toolkit.fillArea(batch, cursorXOnScreen + 2, posY + 27, previewWindowWidth, 20)
|
Toolkit.fillArea(batch, cursorXOnScreen + 2, posY + 27, candidateWinW, candidateWinH)
|
||||||
// compose view border
|
// candidate view border
|
||||||
batch.color = Toolkit.Theme.COL_ACTIVE
|
batch.color = Toolkit.Theme.COL_ACTIVE
|
||||||
Toolkit.drawBoxBorder(batch, cursorXOnScreen + 1, posY + 26, previewWindowWidth + 2, 22)
|
Toolkit.drawBoxBorder(batch, cursorXOnScreen + 1, posY + 26, candidateWinW + 2, candidateWinH + 2)
|
||||||
// compose view text
|
|
||||||
App.fontGame.draw(batch, composingView, cursorXOnScreen + 2 + (previewWindowWidth - previewTextWidth) / 2, posY + 27)
|
// candidate view text
|
||||||
|
for (i in candidates.indices) {
|
||||||
|
val previewTextWidth = textWidths[i]
|
||||||
|
App.fontGame.draw(batch, candidates[i], cursorXOnScreen + 2 + (candidateWinW - previewTextWidth) / 2, posY + 27 + i * 20)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.render(batch, camera)
|
super.render(batch, camera)
|
||||||
|
|||||||
Reference in New Issue
Block a user