# Option

> Checkbox/radio com crossfade animado — checkbox sozinho, radio em Group.

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

# Option

`Option` é um controle de marcação que alterna entre um ícone "on" e "off" com crossfade animado, mais um rótulo opcional. **Fora de um grupo** comporta-se como **checkbox** (marca/desmarca independente); **dentro de um [`group`](/docs/ui/widgets/group)** comporta-se como **radio button** (exclusão mútua). A diferença visual entre check e radio vem do estilo (`Styles.check()` vs `Styles.radio()`), não da classe.

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

## Quando usar
- Checkbox único ou lista de checkboxes independentes ("Aceito os termos").
- Grupo pequeno de opções exclusivas visíveis ao mesmo tempo (radio) via [`group`](/docs/ui/widgets/group).

## Quando NÃO usar
- Para um liga/desliga com metáfora de interruptor → use [`switch`](/docs/ui/widgets/switch).
- Para muitas opções exclusivas (economizando espaço) → use [`dropdown`](/docs/ui/widgets/dropdown).

## Aparência
Ícone on/off (do `OptionStyle`) + rótulo opcional. O alinhamento do ícone (`iconAlignH`/`iconAlignV`) define o lado; o texto ocupa o lado oposto (`textAlignH`/`textAlignV`). O `progress` (0→1) mistura os alfas dos dois ícones durante a transição.

## Exemplo completo (copiar, colar e rodar)
```java
package com.exemplo;

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

/** Tela principal executável. Aponte o launcher (classname) e rode: 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 independente (sem 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: três opções exclusivas dentro de um 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);
   }
}
```

> Os trechos abaixo mostram **só o miolo** (o que vai dentro de `onShow()`). Para rodar, coloque-os no esqueleto `MainWindow` acima.

## 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);
```

## Construtores
| Construtor | Descrição |
|---|---|
| `Option()` | Desmarcado, sem rótulo. |
| `Option(String text)` | Desmarcado, com rótulo. |

## Propriedades e personalização
| Propriedade / método | Tipo | Padrão | O que faz |
|---|---|---|---|
| `text(String)` | `Option` (fluente) | `null` | Define o rótulo. |
| `checked(boolean)` | `Option` (fluente) | `false` | Estado inicial **sem** animação; notifica o grupo. |
| `setChecked(boolean)` | `void` | — | Estado **com** animação (crossfade); notifica o grupo. |
| `toggle()` | `void` | — | Alterna o estado (respeitando o grupo). |
| `checked` | `boolean` (campo) | `false` | Estado lógico atual (pode ser lido/escrito direto). |
| `.group(Group)` | `Option` (fluente) | — | Associa a um [`group`](/docs/ui/widgets/group) → vira radio. |

## Callbacks e eventos
| Callback | Quando dispara |
|---|---|
| `onAction(Action)` | Em `onTouchUp`, **apenas se** `checked` mudou. |

## Estados
- **checked / unchecked**: via `checked(boolean)` (sem animação) ou `setChecked(boolean)` (crossfade). O campo público `checked` também pode ser atribuído direto.
- **radio (em grupo)**: `toggle()` impede desmarcar o item já selecionado; marcar outro desmarca este automaticamente.

### Radio: três opções exclusivas num 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 qualquer uma desmarca as demais automaticamente.
```

## Boas práticas
- Para radios, chame `.group(g)` em **todas** as opções e distinga com `Styles.radio()`; para checkboxes, omita o grupo e use `Styles.check()`.
- Prefira `checked(boolean)` ao campo `checked` para o estado inicial: ele também ajusta `progress` e notifica o grupo.

## Erros comuns
- Esquecer `.group(g)` em alguma opção: sem grupo elas viram checkboxes independentes (sem exclusão mútua).
- Esperar "desmarcar" um radio clicando nele: `toggle()` bloqueia isso dentro de grupo.

## Veja também
- Guia da área: [`ui/`](/docs/ui) · Receitas: [`cookbook/`](/docs/cookbook)
- Conceito (estilos por estado): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`group`](/docs/ui/widgets/group) · [`switch`](/docs/ui/widgets/switch) · [`dropdown`](/docs/ui/widgets/dropdown)
