# Máscaras y teclados

> EditMode (fecha/hora/moneda), máscara con '9', teclados nativos y el Keypad integrado.

Source: https://crossfly.dev/es/docs/ui/forms-and-input/masks-and-keyboards — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Máscaras y teclados

El `EditMode` del campo controla **dos cosas al mismo tiempo**: el **formato** (máscara) y el
**teclado** que se abre. Es la pieza central de la entrada estructurada.

## `EditMode` → teclado
| `EditMode` | Formato | Teclado que abre |
|---|---|---|
| `NORMAL` | ninguno | teclado predeterminado del SO |
| `NUMERIC` | dígitos | numérico nativo (`Keypad` en escritorio) |
| `DATE` | máscara de fecha | **DatePicker** |
| `TIME` | máscara de hora | **TimePicker** |
| `CURRENCY` | moneda (separadores) | **Keypad** calculadora |
| `PASSWORD` | oculta caracteres | teclado predeterminado |

## Ejemplo completo (copiar, pegar y ejecutar)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // TextFieldStyle (config de comportamiento)

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // Campo de fecha: la máscara activada abre el DatePicker al tocar
      TextField data = new TextField().caption("Data");
      data.setMode(EditMode.DATE, true);      // maskedEdit=true → formatea y abre DatePicker
      add(LAY_AUTO, data);

      // Campo de moneda: formatea como moneda al escribir
      TextField valor = new TextField().caption("Valor");
      valor.setMode(EditMode.CURRENCY, true);
      valor.<TextFieldStyle>getStyle().decimalPlaces(2);
      add(LAY_AUTO, valor);

      // Etiqueta donde se mostrarán los valores leídos
      Label resultado = new Label("");
      add(LAY_AUTO, resultado);

      // NO hay callback por tecla: lee getText() al enviar.
      // getTextWithoutMask() devuelve solo los dígitos (bueno p/ guardar en la base).
      Button enviar = new Button("Enviar");
      enviar.onAction(c -> resultado.setText(
         "Data = " + data.getText() + "  |  Valor = " + valor.getTextWithoutMask()));
      add(LAY_AUTO, enviar);
   }
}
```

> Los fragmentos siguientes muestran **solo el núcleo** (lo que va dentro de `onShow()`). Para ejecutar, colócalos en el esqueleto `MainWindow` de arriba.

## Activar máscara automática
`setMode(mode, true)` activa el formato en tiempo real (`maskedEdit`):
```java
TextField data = new TextField().caption("Data");
data.setMode(EditMode.DATE, true);         // al escribir, se vuelve 15/03/2024 y abre el DatePicker

TextField valor = new TextField().caption("Valor");
valor.setMode(EditMode.CURRENCY, true);    // formatea como moneda al escribir
valor.<TextFieldStyle>getStyle().decimalPlaces(2);
```

## Máscara personalizada (el `'9'` es el dígito)
En una máscara, cada `'9'` es una posición de dígito; los demás caracteres son literales fijos:
```java
TextField cpf = new TextField().caption("CPF");
cpf.<TextFieldStyle>getStyle()
   .mask("999.999.999-99".toCharArray())    // 11 dígitos + separadores
   .mode(EditMode.NUMERIC, true);
// getText()          -> "123.456.789-00"  (con máscara)
// getTextWithoutMask()-> "12345678900"    (solo dígitos)
```
Moneda lista: `TextField.getDefaultCurrencyMask(int casasDecimais)` genera la máscara con los separadores
de miles/decimal del locale.

## Elegir el teclado explícitamente
```java
campo.keyboard(Keyboard.NUMERIC);   // fuerza numérico
campo.keyboard(Keyboard.NONE);      // nunca abre teclado (campo de solo lectura visual)
```
`Keyboard` (en `UIConstants`): `NONE, DEFAULT, NUMERIC, KEYPAD, CALCULATOR, DATE, TIME`. `DEFAULT`
adopta el teclado implícito en el `EditMode` actual.

## Keypad integrado
`Keyboard.KEYPAD`/`CALCULATOR` usan el componente **`Keypad`** del propio CrossFly (no el teclado del
SO) — útil en quioscos/PDV. Se abre automáticamente por el campo; para usarlo por separado:
```java
new Keypad(meuCampo).show();        // teclado numérico ligado al campo
```

## Buenas prácticas
- Guarda en la base de datos el **`getTextWithoutMask()`** (dígitos crudos); muéstralo con máscara.
- Combina `mask(...)` con `mode(EditMode.NUMERIC, true)` para documentos (CPF, código postal, teléfono).
- En escritorio, `NUMERIC` recurre al `Keypad` automáticamente — no asumas un teclado nativo.

## Errores comunes
- Activar `mode(EditMode.DATE)` **sin** `maskedEdit=true` → sin formato automático.
- Persistir `getText()` (con puntos/guiones) cuando el back-end espera solo dígitos.
- Máscara sin ningún `'9'` → no se acepta ningún dígito.

## Ver también
- [Campos de texto](/docs/ui/forms-and-input/text-fields) · Catálogo: [DatePicker](/docs/ui/widgets/datepicker) · [TimePicker](/docs/ui/widgets/timepicker) · [Keypad](/docs/ui/widgets/keypad)
