package com.rizoma.trazo.ui import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.rizoma.trazo.model.Dir import com.rizoma.trazo.model.KeyDef import com.rizoma.trazo.model.directionOf import com.rizoma.trazo.ui.theme.NeonVerde import com.rizoma.trazo.ui.theme.Tecla import com.rizoma.trazo.ui.theme.Tenue private val hintAlignments = mapOf( Dir.N to Alignment.TopCenter, Dir.NE to Alignment.TopEnd, Dir.E to Alignment.CenterEnd, Dir.SE to Alignment.BottomEnd, Dir.S to Alignment.BottomCenter, Dir.SW to Alignment.BottomStart, Dir.W to Alignment.CenterStart, Dir.NW to Alignment.TopStart, ) @Composable fun KeyCell( key: KeyDef, shifted: Boolean, onChar: (Char) -> Unit, modifier: Modifier = Modifier, ) { val tapRadiusPx = with(LocalDensity.current) { 22.dp.toPx() } Box( modifier .padding(3.dp) .clip(RoundedCornerShape(14.dp)) .background(Tecla) .border(1.dp, NeonVerde.copy(alpha = 0.10f), RoundedCornerShape(14.dp)) .pointerInput(key, shifted) { awaitEachGesture { val down = awaitFirstDown() var current = down.position while (true) { val event = awaitPointerEvent() val change = event.changes.firstOrNull { it.id == down.id } ?: event.changes.first() current = change.position change.consume() if (!change.pressed) break } val dx = current.x - down.position.x val dy = current.y - down.position.y val dir = directionOf(dx, dy, tapRadiusPx) key.charFor(dir)?.let { raw -> onChar(raw) } } }, ) { // Pistas de swipe (tenues) en los bordes. key.swipes.forEach { (dir, ch) -> val align = hintAlignments[dir] ?: return@forEach Text( text = glyph(ch, shifted), color = Tenue, fontSize = 11.sp, modifier = Modifier.align(align).padding(horizontal = 6.dp, vertical = 3.dp), ) } // Carácter central. Text( text = glyph(key.center, shifted), color = androidx.compose.ui.graphics.Color.White, fontSize = 22.sp, fontWeight = FontWeight.Medium, modifier = Modifier.align(Alignment.Center), ) } } private fun glyph(c: Char, shifted: Boolean): String = if (shifted) c.uppercaseChar().toString() else c.toString()