⎇ e3dd167a16e071c181b3d4f3bc77664f9cf053ab
keyboard/src/main/java/com/rizoma/trazo/ime/KeyboardController.kt
History
raw
Trazo: teclado MessagEase remasterizado (IME v0.1)
1package com.rizoma.trazo.ime
2
3import androidx.compose.runtime.getValue
4import androidx.compose.runtime.mutableStateOf
5import androidx.compose.runtime.setValue
6import com.rizoma.trazo.model.Layouts
7
8/** Puente con el editor real. Lo implementa el InputMethodService. */
9interface ImeHost {
10 fun commit(text: String)
11 fun backspace()
12 fun newline()
13 fun textBeforeCursor(n: Int): CharSequence
14 /** TextUtils.CAP_MODE_* combinado: !=0 si el editor quiere mayúscula aquí. */
15 fun cursorCapsMode(): Int
16}
17
18enum class ShiftState { OFF, ON, LOCK }
19enum class Layer { LETTERS, SYMBOLS }
20
21/**
22 * Toda la lógica de escritura. La UI solo dispara eventos; el estado de mayúscula
23 * y de capa son observables por Compose.
24 */
25class KeyboardController(private val host: ImeHost) {
26
27 var shift by mutableStateOf(ShiftState.ON)
28 private set
29 var layer by mutableStateOf(Layer.LETTERS)
30 private set
31
32 val keys get() = if (layer == Layer.LETTERS) Layouts.letters else Layouts.symbols
33 val shifted get() = shift != ShiftState.OFF
34
35 fun onChar(raw: Char) {
36 val out = if (shifted) raw.uppercaseChar() else raw
37 host.commit(out.toString())
38 if (shift == ShiftState.ON) shift = ShiftState.OFF // mayúscula de un solo disparo
39 }
40
41 fun onSpace() {
42 // Doble espacio tras palabra → ". " (puntua y capitaliza).
43 val before = host.textBeforeCursor(2)
44 if (before.length == 2 && before[1] == ' ' && before[0].isLetterOrDigit()) {
45 host.backspace()
46 host.commit(". ")
47 } else {
48 host.commit(" ")
49 }
50 syncAutoShift()
51 }
52
53 fun onBackspace() {
54 host.backspace()
55 syncAutoShift()
56 }
57
58 fun onEnter() {
59 host.newline()
60 syncAutoShift()
61 }
62
63 fun onShift() {
64 shift = when (shift) {
65 ShiftState.OFF -> ShiftState.ON
66 ShiftState.ON -> ShiftState.LOCK
67 ShiftState.LOCK -> ShiftState.OFF
68 }
69 }
70
71 fun toggleLayer() {
72 layer = if (layer == Layer.LETTERS) Layer.SYMBOLS else Layer.LETTERS
73 }
74
75 /** Recalcula la mayúscula automática según el contexto del editor. */
76 fun syncAutoShift() {
77 if (shift == ShiftState.LOCK) return
78 shift = if (host.cursorCapsMode() != 0) ShiftState.ON else ShiftState.OFF
79 }
80}