# Group

> Logical registry that makes Options/Switches mutually exclusive (radio).

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

# Group

`Group` groups "checkable" components ([`option`](/docs/ui/widgets/option), [`switch`](/docs/ui/widgets/switch) and any `Checkable`) for **mutually exclusive selection** — radio button behavior. When one member is checked, the others are unchecked automatically, optionally with an animated transition (fade). It is not a `Component`: **it draws nothing**, it is just a registry of members + the exclusion logic.

> 🟢 · **Package:** `dev.crossfly.ui` · **Extends:** `java.lang.Object` (not visual) · **Style:** — (no style of its own)

## When to use
- Turn a set of [`option`](/docs/ui/widgets/option) into exclusive radio buttons.
- Make a set of [`switch`](/docs/ui/widgets/switch) or any `Checkable` of yours exclusive.

## When NOT to use
- For a single toggle → a [`switch`](/docs/ui/widgets/switch) or [`option`](/docs/ui/widgets/option) without a group is enough.

## Appearance
None. `Group` is purely logical. The appearance of each button is the responsibility of the members (which must be checkable visual components).

## Complete example (copy, paste and run)
```java
package com.exemplo;

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

/** Runnable main screen. Point the launcher (classname) and run: 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 makes the Options mutually exclusive (radio), with a fade on switch
      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 doesn't store the selected one: each member notifies and we read isChecked()
         o.onAction(c -> {
            for (Option x : ops)
               if (x.isChecked())
                  saida.setText("Selecionado: " + x.text);
         });
         add(LAY_AUTO, o);
      }
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## Basic usage
```java
Group g = new Group().fade(true);                       // fade = animated transition

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);
// When checking any one, the others uncheck with fade.
```

## Constructors
| Constructor | Description |
|---|---|
| `Group()` | Empty group, no fade. |

## Properties and customization
| Property / method | Type | Default | What it does |
|---|---|---|---|
| `fade(boolean)` | `Group` (fluent) | `false` | Turns the animated selection transition on/off. |
| `fade` | `boolean` (field) | `false` | Fade state (read). |
| `add(Component)` | `void` | — | Registers a member (ignores duplicates, by identity). |
| `remove(Component)` | `void` | — | Removes a member (no-op if not a member). |
| `select(Component sender)` | `void` | — | Unchecks all members **except** the `sender`. |

> You normally **don't** call `add`/`select` directly: the checkable itself registers via `.group(group)` and calls `select(this)` when checked.

## Callbacks and events
`Group` has no callbacks. React to changes in each member's `onAction` and query `isChecked()`.

## States
`Group` does not store "which one is selected" — it only ensures the others are turned off when someone reports being checked. **There is no `getSelected()`**: query the state on each member (`isChecked()`).

### Find out which member is selected
```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);

// At some point (e.g.: "Confirm" button):
for (Option o : ops)
   if (o.isChecked())
      System.out.println("selecionado: " + o.text);
```

## Best practices
- Let the component handle registration: `.group(g)` already calls `group.add(this)` internally.
- Exclusivity only works because `Option`/`Switch` call `select(this)` when checked; your own `Checkable` must do the same.

## Common mistakes
- Looking for a nonexistent `getSelected()` — iterate over the members querying `isChecked()`.
- Forgetting `.group(g)` on a member: it stays out of the mutual exclusion.

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (component composition): [`concepts/`](/docs/concepts)
- Related components: [`option`](/docs/ui/widgets/option) · [`switch`](/docs/ui/widgets/switch)
