# Option

> Checkbox/radio con crossfade animado — checkbox solo, radio en Group.

Source: https://crossfly.dev/es/docs/ui/widgets/option — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Option

`Option` es un control de marcación que alterna entre un ícono "on" y "off" con crossfade animado, más un rótulo opcional. **Fuera de un grupo** se comporta como **checkbox** (marca/desmarca independiente); **dentro de un [`group`](/docs/ui/widgets/group)** se comporta como **radio button** (exclusión mutua). La diferencia visual entre check y radio viene del estilo (`Styles.check()` vs `Styles.radio()`), no de la clase.

> 🟢 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Component` (implementa `Checkable`, `AlphaAnimation.Animate`) · **Estilo:** `OptionStyle`

## Cuándo usar
- Checkbox único o lista de checkboxes independientes ("Acepto los términos").
- Grupo pequeño de opciones exclusivas visibles al mismo tiempo (radio) vía [`group`](/docs/ui/widgets/group).

## Cuándo NO usar
- Para un encender/apagar con metáfora de interruptor → usa [`switch`](/docs/ui/widgets/switch).
- Para muchas opciones exclusivas (ahorrando espacio) → usa [`dropdown`](/docs/ui/widgets/dropdown).

## Apariencia
Ícono on/off (del `OptionStyle`) + rótulo opcional. La alineación del ícono (`iconAlignH`/`iconAlignV`) define el lado; el texto ocupa el lado opuesto (`textAlignH`/`textAlignV`). El `progress` (0→1) mezcla los alfas de los dos íconos durante la transición.

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

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;   // Styles.check() / Styles.radio()

/** 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());

      Label saida = new Label("Escolha uma opção");
      add(LAY_AUTO, saida);

      // Checkbox independiente (sin grupo)
      Option aceito = new Option("Aceito os termos").style(Styles.check().copy());
      aceito.onAction(c -> saida.setText("Termos: " + (aceito.checked ? "aceitos" : "recusados")));
      add(LAY_AUTO, aceito);

      // Radio: tres opciones exclusivas dentro de un Group
      Group pagamento = new Group();
      Option cartao = new Option("Cartão").style(Styles.radio().copy()).group(pagamento).checked(true);
      Option boleto = new Option("Boleto").style(Styles.radio().copy()).group(pagamento);
      Option pix    = new Option("Pix").style(Styles.radio().copy()).group(pagamento);

      Component.Action mostra = c -> {
         String sel = cartao.isChecked() ? "Cartão" : boleto.isChecked() ? "Boleto" : "Pix";
         saida.setText("Pagamento: " + sel);
      };
      cartao.onAction(mostra);
      boleto.onAction(mostra);
      pix.onAction(mostra);

      add(LAY_AUTO, cartao);
      add(LAY_AUTO, boleto);
      add(LAY_AUTO, pix);
   }
}
```

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

## Uso básico
```java
Option aceito = new Option("Aceito os termos");
aceito.style(Styles.check().copy());
aceito.checked(true);                                   // marcado inicialmente
aceito.onAction(c -> System.out.println("aceito: " + aceito.checked));
container.add(LAY_AUTO, aceito);
```

## Constructores
| Constructor | Descripción |
|---|---|
| `Option()` | Sin marcar, sin rótulo. |
| `Option(String text)` | Sin marcar, con rótulo. |

## Propiedades y personalización
| Propiedad / método | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `text(String)` | `Option` (fluido) | `null` | Define el rótulo. |
| `checked(boolean)` | `Option` (fluido) | `false` | Estado inicial **sin** animación; notifica al grupo. |
| `setChecked(boolean)` | `void` | — | Estado **con** animación (crossfade); notifica al grupo. |
| `toggle()` | `void` | — | Alterna el estado (respetando el grupo). |
| `checked` | `boolean` (campo) | `false` | Estado lógico actual (puede leerse/escribirse directo). |
| `.group(Group)` | `Option` (fluido) | — | Asocia a un [`group`](/docs/ui/widgets/group) → se vuelve radio. |

## Callbacks y eventos
| Callback | Cuándo se dispara |
|---|---|
| `onAction(Action)` | En `onTouchUp`, **solo si** `checked` cambió. |

## Estados
- **checked / unchecked**: vía `checked(boolean)` (sin animación) o `setChecked(boolean)` (crossfade). El campo público `checked` también puede asignarse directo.
- **radio (en grupo)**: `toggle()` impide desmarcar el ítem ya seleccionado; marcar otro desmarca este automáticamente.

### Radio: tres opciones exclusivas en un Group
```java
Group g = new Group();

Option a = new Option("Opção A").style(Styles.radio().copy()).group(g).checked(true);
Option b = new Option("Opção B").style(Styles.radio().copy()).group(g);
Option c = new Option("Opção C").style(Styles.radio().copy()).group(g);

container.add(LAY_AUTO, a);
container.add(LAY_AUTO, b);
container.add(LAY_AUTO, c);
// Marcar cualquiera desmarca las demás automáticamente.
```

## Buenas prácticas
- Para radios, llama a `.group(g)` en **todas** las opciones y distínguelas con `Styles.radio()`; para checkboxes, omite el grupo y usa `Styles.check()`.
- Prefiere `checked(boolean)` al campo `checked` para el estado inicial: también ajusta `progress` y notifica al grupo.

## Errores comunes
- Olvidar `.group(g)` en alguna opción: sin grupo se vuelven checkboxes independientes (sin exclusión mutua).
- Esperar "desmarcar" un radio haciendo clic en él: `toggle()` bloquea eso dentro de un grupo.

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (estilos por estado): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`group`](/docs/ui/widgets/group) · [`switch`](/docs/ui/widgets/switch) · [`dropdown`](/docs/ui/widgets/dropdown)
