# Group

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

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

# Group

`Group` agrupa componentes "chequeables" ([`option`](/docs/ui/widgets/option), [`switch`](/docs/ui/widgets/switch) y cualquier `Checkable`) para **selección mutuamente exclusiva** — comportamiento de radio button. Cuando un miembro se marca, los demás se desmarcan automáticamente, opcionalmente con transición animada (fade). No es un `Component`: **no dibuja nada**, es solo un registro de miembros + la lógica de exclusión.

> 🟢 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `java.lang.Object` (no es visual) · **Estilo:** — (sin estilo propio)

## Cuándo usar
- Transformar un conjunto de [`option`](/docs/ui/widgets/option) en radio buttons exclusivos.
- Hacer exclusivo un conjunto de [`switch`](/docs/ui/widgets/switch) o cualquier `Checkable` tuyo.

## Cuándo NO usar
- Para una única alternancia → [`switch`](/docs/ui/widgets/switch) o [`option`](/docs/ui/widgets/option) sin grupo bastan.

## Apariencia
Ninguna. `Group` es puramente lógico. La apariencia de cada botón es responsabilidad de los miembros (que deben ser componentes visuales chequeables).

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

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

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

      // Group hace las Options mutuamente exclusivas (radio), con fade al cambiar
      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 no guarda el seleccionado: cada miembro avisa y nosotros leemos isChecked()
         o.onAction(c -> {
            for (Option x : ops)
               if (x.isChecked())
                  saida.setText("Selecionado: " + x.text);
         });
         add(LAY_AUTO, o);
      }
   }
}
```

> Los fragmentos siguientes 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
Group g = new Group().fade(true);                       // fade = transición 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);
// Al marcar cualquiera, las demás se desmarcan con fade.
```

## Constructores
| Constructor | Descripción |
|---|---|
| `Group()` | Grupo vacío, sin fade. |

## Propiedades y personalización
| Propiedad / método | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `fade(boolean)` | `Group` (fluido) | `false` | Activa/desactiva la transición animada de selección. |
| `fade` | `boolean` (campo) | `false` | Estado del fade (lectura). |
| `add(Component)` | `void` | — | Registra un miembro (ignora duplicado, por identidad). |
| `remove(Component)` | `void` | — | Elimina un miembro (no-op si no es miembro). |
| `select(Component sender)` | `void` | — | Desmarca todos los miembros **excepto** el `sender`. |

> Normalmente **no** llamas a `add`/`select` directamente: el propio chequeable se registra vía `.group(group)` y llama a `select(this)` cuando se marca.

## Callbacks y eventos
`Group` no tiene callbacks. Reacciona a los cambios en el `onAction` de cada miembro y consulta `isChecked()`.

## Estados
`Group` no guarda "cuál está seleccionado" — solo garantiza que los demás queden apagados cuando alguien avisa que fue marcado. **No hay `getSelected()`**: consulta el estado en cada miembro (`isChecked()`).

### Descubrir qué miembro está seleccionado
```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);

// En algún punto (ej.: botón "Confirmar"):
for (Option o : ops)
   if (o.isChecked())
      System.out.println("selecionado: " + o.text);
```

## Buenas prácticas
- Deja el registro a cargo del componente: `.group(g)` ya llama a `group.add(this)` internamente.
- La exclusividad solo funciona porque `Option`/`Switch` llaman a `select(this)` al ser marcados; un `Checkable` propio debe hacer lo mismo.

## Errores comunes
- Buscar un `getSelected()` inexistente — itera por los miembros consultando `isChecked()`.
- Olvidar `.group(g)` en algún miembro: queda fuera de la exclusión mutua.

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (composición de componentes): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`option`](/docs/ui/widgets/option) · [`switch`](/docs/ui/widgets/switch)
