tawasuyu

sergio/humanoid

HTML 13TOML 10 Definiciones

⎇ e3dd167a16e071c181b3d4f3bc77664f9cf053ab keyboard/src/main/java/com/rizoma/trazo/model/KeyLayout.kt 75 líneas · 2.8 KB Historia crudo

Trazo: teclado MessagEase remasterizado (IME v0.1) e3dd167a1 · sergio ·

1package com.rizoma.trazo.model
2
3import kotlin.math.atan2
4import kotlin.math.hypot
5
6/** Las 9 direcciones de una tecla: centro (toque) + 8 swipes. */
7enum class Dir { C, N, NE, E, SE, S, SW, W, NW }
8
9/**
10 * Una tecla del grid 3x3. [center] es el toque; [swipes] mapea cada dirección
11 * de deslizamiento a su carácter. Todo es dato → la distribución se ajusta sin tocar UI.
12 */
13data class KeyDef(
14    val center: Char,
15    val swipes: Map<Dir, Char> = emptyMap(),
16) {
17    fun charFor(dir: Dir): Char? = if (dir == Dir.C) center else swipes[dir]
18}
19
20object Layouts {
21
22    /**
23     * Letras — remaster del espíritu MessagEase para español.
24     * Los 9 toques son las letras más frecuentes en su posición MessagEase clásica
25     * (A N I / H O R / T E S). Las 8 direcciones del centro (O) llevan las secundarias
26     * frecuentes; las raras y la Ñ van en los bordes. Tweakable a gusto.
27     */
28    val letters: List<KeyDef> = listOf(
29        // fila superior
30        KeyDef('a', mapOf(Dir.E to 'q', Dir.S to 'z')),
31        KeyDef('n', mapOf(Dir.S to 'f', Dir.E to 'v')),
32        KeyDef('i', mapOf(Dir.S to 'j', Dir.W to 'k')),
33        // fila media
34        KeyDef('h', mapOf(Dir.N to 'w', Dir.S to 'x')),
35        KeyDef(
36            'o',
37            mapOf(
38                Dir.N to 'u', Dir.NE to 'b', Dir.E to 'c', Dir.SE to 'd',
39                Dir.S to 'g', Dir.SW to 'p', Dir.W to 'm', Dir.NW to 'l',
40            ),
41        ),
42        KeyDef('r', mapOf(Dir.S to 'y')),
43        // fila inferior
44        KeyDef('t', mapOf(Dir.N to 'ñ')),
45        KeyDef('e', emptyMap()),
46        KeyDef('s', emptyMap()),
47    )
48
49    /**
50     * Números y símbolos. Dígitos 1-9 en posición de marcador telefónico; 0 y la
51     * puntuación frecuente como swipes.
52     */
53    val symbols: List<KeyDef> = listOf(
54        KeyDef('1', mapOf(Dir.N to '!', Dir.E to '@')),
55        KeyDef('2', mapOf(Dir.N to '"', Dir.E to '#')),
56        KeyDef('3', mapOf(Dir.N to '\'', Dir.W to '$')),
57        KeyDef('4', mapOf(Dir.N to '%', Dir.E to '&')),
58        KeyDef('5', mapOf(Dir.N to '*', Dir.E to '+', Dir.W to '-', Dir.S to '=')),
59        KeyDef('6', mapOf(Dir.N to '/', Dir.W to '\\')),
60        KeyDef('7', mapOf(Dir.N to '(', Dir.E to ')')),
61        KeyDef('8', mapOf(Dir.N to ',', Dir.E to '.', Dir.W to '?')),
62        KeyDef('9', mapOf(Dir.N to ';', Dir.W to ':', Dir.E to '0')),
63    )
64}
65
66/** Geometría: convierte el delta de un gesto en una de las 9 direcciones. */
67fun directionOf(dx: Float, dy: Float, tapRadiusPx: Float): Dir {
68    if (hypot(dx, dy) < tapRadiusPx) return Dir.C
69    var deg = Math.toDegrees(atan2(dy.toDouble(), dx.toDouble())) // 0=E, 90=S (y hacia abajo)
70    if (deg < 0) deg += 360.0
71    // 8 sectores de 45° centrados en cada eje.
72    val order = arrayOf(Dir.E, Dir.SE, Dir.S, Dir.SW, Dir.W, Dir.NW, Dir.N, Dir.NE)
73    val idx = (((deg + 22.5) / 45.0).toInt()) % 8
74    return order[idx]
75}