# WebContainer

> Embute uma webview nativa (HTML/JS) dentro da UI — via a interface IWebView, dependente de plataforma.

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

# WebContainer

`WebContainer` é um widget que **embute uma webview nativa** (conteúdo HTML/JavaScript) dentro da sua UI CrossFly. Ele é um *wrapper* fino: não desenha nada próprio — delega tudo à `IWebView` que a plataforma fornece via `PlatformUtils.instance.createWebView()`. Serve para exibir uma página, um formulário HTML ou um painel web como se fosse um componente comum da tela.

> ⚠️ **Honestidade sobre disponibilidade:** `WebContainer` **só funciona onde existe uma `IWebView` nativa** (Android, iOS, Desktop). **Não há implementação concreta de `IWebView` nesta base de código nem no alvo Web/TeaVM** — `createWebView()` retorna `null` em plataformas sem suporte, e o construtor de `WebContainer` então lança `UnsupportedOperationException`. Num build Web/WebGL, prefira abrir uma página externa (`view(url)`) em vez de embutir uma webview.

> 🔴 · **Pacote:** `dev.crossfly.ui` · **Estende:** `Component` (implementa `Runnable`) · **Delega para:** `IWebView`

## Quando usar
- Exibir conteúdo web (HTML/JS) **dentro** do app, numa plataforma com webview nativa (Android/iOS/Desktop).
- Integrar um formulário HTML e capturar o envio via `setFormSubmitListener`.

## Quando NÃO usar
- Para conteúdo estático simples (texto/imagem) → use os widgets nativos ([`chartview`](/docs/ui/widgets/chartview), labels, imagens) em vez de carregar uma página.

## Aparência
`WebContainer` não pinta pixels próprios: a webview nativa do sistema é sobreposta à área do componente. A visibilidade é coordenada automaticamente em `onPaint` — a webview aparece apenas quando a janela pai está no topo (`isTopMost()`) e some caso contrário.

## Exemplo completo (copiar, colar e rodar)
`WebContainer` só funciona onde há uma `IWebView` nativa. O exemplo detecta o suporte com `PlatformUtils.instance.createWebView() != null` **antes** de criar o container (evitando o `UnsupportedOperationException` do construtor) e, sem suporte (ex.: alvo Web/TeaVM), degrada abrindo a página externamente com `view(url)`.

```java
package com.exemplo;

import dev.crossfly.PlatformUtils;

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

      String url = "https://example.com";

      // Só cria o WebContainer se a plataforma fornecer uma IWebView nativa.
      if (PlatformUtils.instance.createWebView() != null)
      {
         WebContainer browser = new WebContainer();
         browser.show(url);
         add(LAY_FILL, browser);
      }
      else
      {
         // Alvo Web/TeaVM (sem webview embutida): abre a página externamente.
         add(LAY_AUTO, new Label("Sem webview nativa — abrindo externamente…"));
         PlatformUtils.instance.view(url);
      }
   }
}
```

> 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
WebContainer browser = new WebContainer();   // pode lançar UnsupportedOperationException
browser.show("https://example.com");
container.add(LAY_FILL, browser);
```

## Construtores
| Construtor | Descrição |
|---|---|
| `WebContainer()` | Obtém a webview nativa via `PlatformUtils.instance.createWebView()` e inicia invisível. **Lança `UnsupportedOperationException`** se a plataforma não fornecer uma `IWebView`. |

## Propriedades e personalização
| Método | Tipo | O que faz |
|---|---|---|
| `show(String url)` | `void` | Carrega e exibe a URL na webview. |
| `hide()` | `void` | Esconde a webview mantendo o estado da página. |
| `setVisible(boolean)` | `void` | `true` = `show(null)` (mantém URL/estado atual); `false` = `hide()`. |
| `isVisible()` | `boolean` | Se a webview está visível. |
| `evaluateJavaScript(String script)` | `void` | Executa JavaScript na página. |
| `setFormSubmitListener(IWebView.FormSubmitListener)` | `void` | Registra callback para captura de envios de formulário HTML. |

> A `IWebView` exige que as operações ocorram na *render thread* (paint thread). Volte a ela com `Component.onUI(...)` se estiver chamando `show`/`evaluateJavaScript` de outra thread.

## Callbacks e eventos
| Callback | Quando dispara |
|---|---|
| `IWebView.FormSubmitListener` (via `setFormSubmitListener`) | Ao enviar um formulário HTML dentro da página embutida. |

> `WebContainer` **não usa** `onAction`/`onClick` — a interação acontece dentro da página web. O único gancho de app é o listener de submit de formulário.

## Estados
- **visível / oculto**: gerenciado por `show`/`hide`/`setVisible` e, automaticamente, pela posição da janela (a webview some quando a janela pai não está no topo).
- **removido**: no `onRemove`, `view.removeView()` é chamado e a `IWebView` **não pode ser reutilizada** — para reexibir, crie um novo `WebContainer`.

### Formulário HTML com captura de envio (plataforma com webview)
```java
WebContainer form = new WebContainer();
form.setFormSubmitListener(dados -> processarEnvio(dados));  // IWebView.FormSubmitListener
form.show("https://meuservico/formulario.html");
container.add(LAY_FILL, form);
```

### Degradação segura no alvo Web
```java
// No build Web/TeaVM, createWebView() retorna null e o construtor lança.
try {
   WebContainer c = new WebContainer();
   c.show("https://example.com");
   container.add(LAY_FILL, c);
} catch (UnsupportedOperationException e) {
   // Sem webview embutida: abra a página externamente.
   PlatformUtils.instance.view("https://example.com");
}
```

## Boas práticas
- Encapsule a criação num `try/catch` de `UnsupportedOperationException` para degradar bem no alvo Web.

## Erros comuns
- **Criar `WebContainer` em plataforma sem suporte**: lança `UnsupportedOperationException`. Trate ou detecte antes.
- **Reutilizar após `onRemove`**: a `IWebView` foi descartada (`removeView()`); crie uma nova instância.
- **Esperar embutir web no alvo Web/TeaVM**: não há implementação; embutir webview ≠ ser um app web. Use `view(url)`.

## Veja também
- Guia da área: [`ui/`](/docs/ui) · Receitas: [`cookbook/`](/docs/cookbook)
- Conceito (plataformas, threading de UI): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`locationview`](/docs/ui/widgets/locationview)
