tawasuyu

sergio/humanoid

HTML 13TOML 10 Definiciones

⎇ b021d6829a602218866114f86e2350d80f0500e2 keyboard/src/main/java/com/rizoma/trazo/model/KeyLayout.kt 81 líneas · 3.0 KB Historia crudo

Trazo: layout MessagEase auténtico + fila de funciones sobre la barra de nav f809af7f4 · 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 — layout MessagEase AUTÉNTICO (inglés), tomado de la fuente de Thumb-Key
24     * (sucesor FOSS de MessagEase). Toques A N I / H O R / T E S; las secundarias en su
25     * dirección de trazo original (V = A↘ hacia O, D = O↓, C = O←, etc.).
26     * Añadido para español: Ñ con trazo ↑ en la N. Puntuación frecuente en la E.
27     */
28    val letters: List<KeyDef> = listOf(
29        // fila superior: A N I
30        KeyDef('a', mapOf(Dir.SE to 'v')),
31        KeyDef('n', mapOf(Dir.S to 'l', Dir.N to 'ñ')),
32        KeyDef('i', mapOf(Dir.SW to 'x')),
33        // fila media: H O R
34        KeyDef('h', mapOf(Dir.E to 'k')),
35        KeyDef(
36            'o',
37            mapOf(
38                Dir.NW to 'q', Dir.N to 'u', Dir.NE to 'p', Dir.E to 'b',
39                Dir.SE to 'j', Dir.S to 'd', Dir.SW to 'g', Dir.W to 'c',
40            ),
41        ),
42        KeyDef('r', mapOf(Dir.W to 'm')),
43        // fila inferior: T E S
44        KeyDef('t', mapOf(Dir.NE to 'y')),
45        KeyDef(
46            'e',
47            mapOf(
48                Dir.N to 'w', Dir.NE to '\'', Dir.E to 'z',
49                Dir.SE to ':', Dir.S to '.', Dir.SW to ',',
50            ),
51        ),
52        KeyDef('s', mapOf(Dir.NW to 'f')),
53    )
54
55    /**
56     * Números y símbolos. Dígitos 1-9 en posición de marcador telefónico; 0 y la
57     * puntuación frecuente como swipes.
58     */
59    val symbols: List<KeyDef> = listOf(
60        KeyDef('1', mapOf(Dir.N to '!', Dir.E to '@')),
61        KeyDef('2', mapOf(Dir.N to '"', Dir.E to '#')),
62        KeyDef('3', mapOf(Dir.N to '\'', Dir.W to '$')),
63        KeyDef('4', mapOf(Dir.N to '%', Dir.E to '&')),
64        KeyDef('5', mapOf(Dir.N to '*', Dir.E to '+', Dir.W to '-', Dir.S to '=')),
65        KeyDef('6', mapOf(Dir.N to '/', Dir.W to '\\')),
66        KeyDef('7', mapOf(Dir.N to '(', Dir.E to ')')),
67        KeyDef('8', mapOf(Dir.N to ',', Dir.E to '.', Dir.W to '?')),
68        KeyDef('9', mapOf(Dir.N to ';', Dir.W to ':', Dir.E to '0')),
69    )
70}
71
72/** Geometría: convierte el delta de un gesto en una de las 9 direcciones. */
73fun directionOf(dx: Float, dy: Float, tapRadiusPx: Float): Dir {
74    if (hypot(dx, dy) < tapRadiusPx) return Dir.C
75    var deg = Math.toDegrees(atan2(dy.toDouble(), dx.toDouble())) // 0=E, 90=S (y hacia abajo)
76    if (deg < 0) deg += 360.0
77    // 8 sectores de 45° centrados en cada eje.
78    val order = arrayOf(Dir.E, Dir.SE, Dir.S, Dir.SW, Dir.W, Dir.NW, Dir.N, Dir.NE)
79    val idx = (((deg + 22.5) / 45.0).toInt()) % 8
80    return order[idx]
81}