# Group

> Registro lógico que torna Options/Switches mutuamente exclusivos (radio).

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

# Group

`Group` agrupa componentes "checkáveis" ([`option`](/docs/ui/widgets/option), [`switch`](/docs/ui/widgets/switch) e qualquer `Checkable`) para **seleção mutuamente exclusiva** — comportamento de radio button. Quando um membro é marcado, os demais são desmarcados automaticamente, opcionalmente com transição animada (fade). Não é um `Component`: **não desenha nada**, é apenas um registro de membros + a lógica de exclusão.

> 🟢 · **Pacote:** `dev.crossfly.ui` · **Estende:** `java.lang.Object` (não é visual) · **Estilo:** — (sem estilo próprio)

## Quando usar
- Transformar um conjunto de [`option`](/docs/ui/widgets/option) em radio buttons exclusivos.
- Tornar exclusivo um conjunto de [`switch`](/docs/ui/widgets/switch) ou qualquer `Checkable` seu.

## Quando NÃO usar
- Para uma única alternância → [`switch`](/docs/ui/widgets/switch) ou [`option`](/docs/ui/widgets/option) sem grupo bastam.

## Aparência
Nenhuma. `Group` é puramente lógico. A aparência de cada botão é responsabilidade dos membros (que precisam ser componentes visuais checkáveis).

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

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** 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("Selecionado: Cartão");
      add(LAY_AUTO, saida);

      // Group torna as Options mutuamente exclusivas (radio), com fade na troca
      Group g = new Group().fade(true);

      Option[] ops = {
         new Option("Cartão").group(g).checked(true),
         new Option("Boleto").group(g),
         new Option("Pix").group(g)
      };

      for (Option o : ops)
      {
         // Group não guarda o selecionado: cada membro avisa e nós lemos isChecked()
         o.onAction(c -> {
            for (Option x : ops)
               if (x.isChecked())
                  saida.setText("Selecionado: " + x.text);
         });
         add(LAY_AUTO, o);
      }
   }
}
```

> 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
Group g = new Group().fade(true);                       // fade = transição animada

Option a = new Option("Opção A").group(g);
Option b = new Option("Opção B").group(g);
Option c = new Option("Opção C").group(g);

container.add(LAY_AUTO, a);
container.add(LAY_AUTO, b);
container.add(LAY_AUTO, c);
// Ao marcar qualquer uma, as outras desmarcam com fade.
```

## Construtores
| Construtor | Descrição |
|---|---|
| `Group()` | Grupo vazio, sem fade. |

## Propriedades e personalização
| Propriedade / método | Tipo | Padrão | O que faz |
|---|---|---|---|
| `fade(boolean)` | `Group` (fluente) | `false` | Liga/desliga a transição animada de seleção. |
| `fade` | `boolean` (campo) | `false` | Estado do fade (leitura). |
| `add(Component)` | `void` | — | Registra um membro (ignora duplicado, por identidade). |
| `remove(Component)` | `void` | — | Remove um membro (no-op se não for membro). |
| `select(Component sender)` | `void` | — | Desmarca todos os membros **exceto** o `sender`. |

> Normalmente você **não** chama `add`/`select` diretamente: o próprio checkável se registra via `.group(group)` e chama `select(this)` quando marcado.

## Callbacks e eventos
`Group` não tem callbacks. Reaja às mudanças no `onAction` de cada membro e consulte `isChecked()`.

## Estados
`Group` não guarda "qual está selecionado" — apenas garante que os demais fiquem desligados quando alguém avisa que foi marcado. **Não há `getSelected()`**: consulte o estado em cada membro (`isChecked()`).

### Descobrir qual membro está selecionado
```java
Group g = new Group();
Option[] ops = {
   new Option("Cartão").group(g).checked(true),
   new Option("Boleto").group(g),
   new Option("Pix").group(g)
};
for (Option o : ops)
   container.add(LAY_AUTO, o);

// Em algum ponto (ex.: botão "Confirmar"):
for (Option o : ops)
   if (o.isChecked())
      System.out.println("selecionado: " + o.text);
```

## Boas práticas
- Deixe o registro por conta do componente: `.group(g)` já chama `group.add(this)` internamente.
- A exclusividade só funciona porque `Option`/`Switch` chamam `select(this)` ao serem marcados; um `Checkable` próprio precisa fazer o mesmo.

## Erros comuns
- Procurar por um `getSelected()` inexistente — itere pelos membros consultando `isChecked()`.
- Esquecer `.group(g)` em algum membro: ele fica fora da exclusão mútua.

## Veja também
- Guia da área: [`ui/`](/docs/ui) · Receitas: [`cookbook/`](/docs/cookbook)
- Conceito (composição de componentes): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`option`](/docs/ui/widgets/option) · [`switch`](/docs/ui/widgets/switch)
