# A pilha de janelas

> O modelo por trás da navegação — a pilha do EventsProcessor, popup vs fullscreen, botão Voltar e transições.

Source: https://crossfly.dev/pt/docs/ui/navigation/the-window-stack — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# A pilha de janelas

Entender o modelo evita a maioria dos bugs de navegação.

## O modelo (LIFO)
O `EventsProcessor` mantém uma **pilha** de `Window`. A janela do topo é a que **recebe eventos e é
pintada por cima**. As de baixo continuam vivas (não são destruídas), apenas cobertas.

```
┌─────────────┐  ← topo: recebe toque/teclado, é pintada
│ TelaDetalhe │
├─────────────┤
│ TelaLista   │  ← coberta, viva
├─────────────┤
│ TelaHome    │  ← base
└─────────────┘
```

- `show()` → **push**: registra no `EventsProcessor`, chama `onShow()`.
- `hide()` → **pop**: desregistra, chama `onRemove()`; a janela de baixo volta ao topo.

## Ciclo de vida por janela
| Método | Quando | Uso |
|---|---|---|
| `onShow()` | ao entrar na pilha | montar a UI (sempre `super.onShow()`) |
| `onReposition()` | ao redimensionar/rotacionar | reorganizar/recalcular layout |
| `onRemove()` | ao sair da pilha | liberar timers, cursores, listeners |

## Fullscreen vs popup
A **mesma** classe `Window` pode ser tela cheia ou popup — depende do `WindowStyle`
(`widthRatio`/`heightRatio` < 1 ⇒ popup; ver [Diálogos e modais](/docs/ui/navigation/dialogs-and-modals)). Popups
ficam sobre a tela anterior (que continua visível atrás).

## Botão Voltar (Android) e tocar fora
- O **botão físico Voltar** é capturado pela aplicação e, por padrão, faz `hide()` da janela do topo.
- Em um popup com `canHide = true`, **tocar fora** fecha o popup.
- Para **impedir** a saída (ex.: confirmação de descarte), trate a intenção antes de deixar `hide()` ocorrer.

## Exemplo completo (copiar, colar e rodar)
Demonstra push/pop na pilha e uma transição de entrada configurada no `WindowStyle` da tela empilhada.
```java
package com.exemplo;

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

/** 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());

      add(LAY_AUTO, new Label("Base da pilha (MainWindow)"));

      Button empilhar = new Button("Empilhar tela (push)");
      empilhar.onAction(c -> new TelaEmpilhada().show());   // push: entra no topo da pilha
      add(LAY_AUTO, empilhar);
   }
}

/** Tela que entra no topo com uma transição e volta com hide() (pop). */
class TelaEmpilhada extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      // transição de entrada/saída desta janela (a de baixo continua viva atrás)
      getStyle().transition(UIConstants.Transition.SLIDE_LEFT);
      setLayout(new VerticalLayout());

      add(LAY_AUTO, new Label("Topo da pilha — a tela de baixo continua viva"));

      Button voltar = new Button("Voltar (pop)");
      voltar.onAction(c -> hide());   // pop: sai da pilha, a de baixo volta ao topo
      add(LAY_AUTO, voltar);
   }
}
```
> Os trechos abaixo mostram **só o miolo** (o que vai dentro de `onShow()`). Para rodar, coloque-os no esqueleto `MainWindow` acima.

## Transições
A animação de entrada/saída vem de `WindowStyle.transition` (`UIConstants.Transition`): `NONE`
(padrão), `FADE`, `SLIDE_LEFT/RIGHT/UP/DOWN`, `SCALE`, `SCALE_DOWN`. Pickers usam `FADE` por padrão.
```java
getStyle().transition = UIConstants.Transition.SLIDE_LEFT;   // desliza ao abrir
```

## Boas práticas
- Não segure referências às janelas de baixo além do necessário — deixe-as serem coletadas ao `hide()`.
- Todo `show()` deve ter um `hide()` correspondente (evite empilhar telas sem retorno).

## Erros comuns
- Reconstruir a UI em `onReposition()` sem preservar estado (rolagem, seleção).
- Assumir que a janela de baixo foi destruída ao abrir outra — ela continua viva.

## Veja também
- [Navegar entre telas](/docs/ui/navigation/navigate-between-screens) · [Diálogos e modais](/docs/ui/navigation/dialogs-and-modals)
