# Switch

> Interruptor on/off com trilho deslizante animado e rótulo opcional.

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

# Switch

`Switch` é um interruptor **liga/desliga** com trilho arredondado e um "thumb" (botão deslizante) que desliza entre os estados off e on de forma animada. Aceita um rótulo de texto opcional ao lado e ícones on/off que fazem crossfade na transição. É o controle ideal para ativar/desativar uma preferência imediata, no estilo iOS/Material.

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

## Quando usar
- Ligar/desligar uma única preferência com efeito imediato (ex.: "Ativar notificações").
- Onde o usuário espera um toggle visual e não uma caixa de marcação.

## Quando NÃO usar
- Para escolher entre várias opções visíveis ao mesmo tempo → use [`option`](/docs/ui/widgets/option) dentro de um [`group`](/docs/ui/widgets/group).
- Para uma lista maior de escolhas → use [`dropdown`](/docs/ui/widgets/dropdown).

## Aparência
Trilho arredondado (`trackRadius = trackH/2`) com um thumb quadrado que se move de `thumbMinX` (off) até `thumbMaxX` (on). Largura, altura do trilho e tamanho do thumb são proporcionais à altura da fonte (`switchWidth`, `trackHeight`, `thumbSizeRatio` do `SwitchStyle`). O rótulo opcional fica ao lado do interruptor; quando `iconAlignH == END` o switch vai à direita e o texto à esquerda, caso contrário o texto fica à direita.

## 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 que reflete o estado do switch
      Label saida = new Label("Recurso: desligado");
      add(LAY_AUTO, saida);

      // Switch com rótulo; onAction só dispara quando o estado muda
      Switch toggle = new Switch("Ativar recurso");
      toggle.checked(false);   // estado inicial, sem animação
      toggle.onAction(c -> saida.setText("Recurso: " + (toggle.checked ? "ligado" : "desligado")));
      add(LAY_AUTO, toggle);
   }
}
```

> 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
Switch toggle = new Switch("Ativar recurso");
toggle.checked(true);                                  // estado inicial, SEM animação
toggle.onAction(c -> System.out.println("estado: " + toggle.checked));
container.add(LAY_AUTO, toggle);
```

## Construtores
| Construtor | Descrição |
|---|---|
| `Switch()` | Desmarcado, sem rótulo (modo somente-ícone). |
| `Switch(String text)` | Desmarcado, com rótulo ao lado. |

## Propriedades e personalização
| Propriedade / método | Tipo | Padrão | O que faz |
|---|---|---|---|
| `text(String)` | `Switch` (fluente) | `null` | Define o rótulo. |
| `checked(boolean)` | `Switch` (fluente) | `false` | Estado inicial **sem** animação (ajusta `progress` direto); notifica o grupo. |
| `setChecked(boolean)` | `void` | — | Estado **com** animação; notifica o grupo. |
| `toggle()` | `void` | — | Alterna o estado (respeitando o grupo). |
| `checked` | `boolean` (campo) | `false` | Estado lógico atual (leitura). |
| `progress` | `float` (campo) | `0` | Posição interpolada do thumb: `0` = off, `1` = on. |
| `.group(Group)` | `Switch` (fluente) | — | Associa a um [`group`](/docs/ui/widgets/group) para exclusão mútua. |

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

## Estados
- **checked / unchecked**: controlado por `checked(boolean)` (sem animação) ou `setChecked(boolean)` (com animação). O campo `checked` reflete o estado.
- **em animação**: `progress` transita de 0 a 1 (ou vice-versa) via `AlphaAnimation` (duração = `style.animationDuration`).
- **em grupo**: `toggle()` **não desmarca** um switch já marcado que pertence a um grupo (comportamento de rádio).

### Vários switches mutuamente exclusivos (rádio) num Group
```java
Group modo = new Group();

Switch claro  = new Switch("Tema claro").group(modo).checked(true);
Switch escuro = new Switch("Tema escuro").group(modo);

container.add(LAY_AUTO, claro);
container.add(LAY_AUTO, escuro);
// Marcar um desmarca o outro automaticamente.
```

## Boas práticas
- Prefira `checked(boolean)` para o estado inicial (ajusta `progress` e o grupo de uma vez); use `setChecked` quando quiser a transição animada em runtime.
- Leia o estado por `isChecked()` ou pelo campo `checked` dentro do `onAction`.

## Erros comuns
- Esperar que `onAction` dispare em toda interação: ele só dispara quando `checked` **muda**.
- Tentar "desligar" clicando num switch já marcado dentro de um `Group`: `toggle()` impede isso (rádio).

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