# TextArea

> Campo de texto multilinha com word-wrap, rolagem vertical, ícones por linha e modo read-only rolável.

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

# TextArea

`TextArea` é a entrada de texto **de múltiplas linhas**. Sobre a base [`TextInput`](/docs/ui/widgets/textinput), adiciona: word-wrap, estrutura de linhas, rolagem vertical, mapeamento de coordenadas 2D e layout multilinha. Suporta ícones à direita (um por linha visível) e um modo **read-only rolável** (para exibir texto longo que o usuário só percorre).

Diferente do [`TextField`](/docs/ui/widgets/textfield), o `TextArea` **não tem máscara nem modo senha**; `ENTER` insere quebra de linha e `getText()` preserva os `\n`.

> 🟡 · **Pacote:** `dev.crossfly.ui` · **Estende:** `TextInput` · **Estilo:** `TextAreaStyle`

## Quando usar
- Observações, comentários, descrições, endereços — qualquer texto de **várias linhas**.
- Exibir um bloco longo rolável (com `editable=false`).

## Quando NÃO usar
- Entrada de **uma linha** (nome, e-mail, valor) → use [`TextField`](/docs/ui/widgets/textfield).
- Máscara / modo senha → use [`TextField`](/docs/ui/widgets/textfield) (o `TextArea` não os suporta).

## Aparência
Retângulo com fundo/borda do `TextAreaStyle`, texto quebrado em linhas (word-wrap na largura interna), com rolagem vertical quando o conteúdo excede a altura. A altura preferida vem de `rowCount` (número de linhas visíveis) × altura de linha + `ingap`. Ícones à direita, quando definidos, ocupam uma coluna própria, um por linha visível.

``

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

      // Campo multilinha; LAY_FILL dá altura à área rolável
      TextArea obs = new TextArea().caption("Observações");
      add(LAY_FILL, obs);

      // Label de saída
      Label saida = new Label("Escreva algo e toque em Enviar");
      add(LAY_AUTO, saida);

      // Não há onChange por tecla: leia getText() no envio (preserva os \n)
      Button enviar = new Button("Enviar")
         .onAction(c -> saida.setText("Você escreveu " + obs.getText().length() + " caracteres"));
      add(LAY_AUTO, enviar);
   }
}
```

> 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
TextArea obs = new TextArea().caption("Observações");
container.add(0.4f, obs);
// ...
String texto = obs.getText();   // preserva os \n
```

## Construtores
| Construtor | Descrição |
|---|---|
| `TextArea()` | vazio |
| `TextArea(String text)` | com texto inicial (`\r\n`/`\r` normalizados para `\n`) |

## Propriedades e personalização
| Propriedade / método | Tipo | Padrão | O que faz |
|---|---|---|---|
| `text(String)` / `setText(String)` | `TextArea` / `void` | — | define o texto (normaliza quebras; cursor ao início) |
| `getText()` | `String` | — | texto bruto, preservando `\n` |
| `caption(String)` | `TextArea` (fluente) | `null` | placeholder |
| `rightIcons(Icon...)` | `TextArea` (fluente) | — | ícones à direita, um por linha visível |
| `rightIconAction(int row, Action)` | `TextArea` (fluente) | — | ação do ícone da linha `row` (0-based) |
| `clearText()` | `void` | — | limpa todo o texto |
| `getNumberOfTextLines()` | `int` | — | total de linhas lógicas (word-wrapped) |
| `scrollToTop()` / `scrollToBottom()` / `scrollToLine(int)` | `void` | — | rolagem programática |
| estilo `.rowCount(int)` | `int` | — | nº de linhas visíveis (define a altura preferida) |
| estilo `.maxLength(int)` | `int` | `0` (ilimitado) | limite de caracteres |
| estilo `.validChars(String)` | `String` | `null` | caracteres permitidos (`\n` sempre aceito) |
| estilo `.editable(false)` | `boolean` | `true` | read-only rolável |
| estilo `.spaceBetweenLines(int)` | `int` | — | espaço extra entre linhas |

## Callbacks e eventos
| Callback | Quando dispara |
|---|---|
| `onAction(Action)` (herdado) | em `onTouchUp`, após abrir o teclado |
| `onFocus()` / `onBlur()` (herdados) | ganho / perda de foco |
| `rightIconAction(row, Action)` | ao tocar (e soltar sobre) o ícone daquela linha |

## Estados
- **focused:** cursor piscando, teclado abre no toque; setas ↑/↓ navegam entre linhas.
- **selection:** seleção 2D por arrasto; long-touch seleciona tudo e abre o `ActionSheet`.
- **read-only (`editable=false`):** sem cursor/edição; o arrasto **rola** o conteúdo; roda do mouse também rola.

### Campo de observações com limite
```java
TextArea obs = new TextArea().caption("Observações");
obs.style(Styles.theme()
   .textArea(State.NORMAL)
   .rowCount(4)
   .maxLength(500));
container.add(LAY_AUTO, obs);
```

### Bloco de texto somente-leitura, rolável
```java
TextArea termos = new TextArea(textoDosTermos);
termos.style(Styles.theme()
   .textArea(State.NORMAL)
   .editable(false)      // apenas rolar, sem editar
   .rowCount(8));
container.add(LAY_FILL, termos);
termos.scrollToTop();
```

### Linhas com ícone de ação à direita
```java
TextArea lista = new TextArea("Item A\nItem B\nItem C");
lista.rightIcons(
   new MaterialIcon(""),   // "delete" na linha 0
   new MaterialIcon(""),
   new MaterialIcon(""));
lista.rightIconAction(0, c -> removerLinha(0));
container.add(0.3f, lista);
```

## Boas práticas
- Defina `rowCount` no estilo para controlar a altura visível; combine com `LAY_AUTO` no layout.
- Para exibir texto longo sem edição, use `editable(false)` — o arrasto passa a rolar em vez de selecionar.
- Use `getText()` para persistir (preserva `\n`); normalização de `\r\n` já é feita na entrada.

## Erros comuns
- **Esperar máscara ou modo senha:** o `TextArea` não os suporta — use [`TextField`](/docs/ui/widgets/textfield).
- **Definir muitos `rightIcons`:** só são desenhados até `visibleRows` (nº de linhas visíveis); ícones além disso são ignorados.

## Veja também
- Guia da área: [`ui/`](/docs/ui) · Receitas: [`cookbook/`](/docs/cookbook)
- Conceito (foco, seleção, scroll): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`TextInput`](/docs/ui/widgets/textinput) · [`TextField`](/docs/ui/widgets/textfield) · [`Keypad`](/docs/ui/widgets/keypad)
