# LocationView

> Exibe as coordenadas de GPS (lat, lon, hora do fix, velocidade, direção) como texto, atualizadas periodicamente.

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

# LocationView

`LocationView` é um widget que **exibe** dados de GPS como texto: latitude e longitude (em graus/minutos/segundos com sufixos N/S e E/W), hora do fix, velocidade, direção e número de satélites. Ele lê periodicamente de uma `Location` (fonte de GPS — porta COM/Bluetooth/IR ou APIs nativas) e atualiza cinco `Label`s empilhados num `VerticalLayout`.

Ele **não desenha mapa** — apenas mostra os números. Para centralizar um mapa na posição do dispositivo, use `Map` (ver Cap. 25).

> 🟡 · **Pacote:** `dev.crossfly.ui` · **Estende:** `Component` · **Fonte de dados:** `dev.crossfly.device.Location`

## Quando usar
- Mostrar as coordenadas atuais do dispositivo em texto (diagnóstico, HUD, tela de status de GPS).
- Ter uma leitura periódica automática de posição sem escrever o loop de timer.

## Quando NÃO usar
- Renderizar um mapa ou marcar a posição visualmente → use `Map` (Cap. 25).
- Só ler a posição uma vez em código, sem UI → use a classe `Location` diretamente.

## Aparência
Cinco linhas de texto (lat, lon, fix, speed, direction), alinhadas à esquerda, num `VerticalLayout`. Enquanto não há dados exibe "Location Initialising"; sem sinal, exibe as strings localizáveis `LAT_LOW_SIGNAL` / `LON_LOW_SIGNAL`.

## Exemplo completo (copiar, colar e rodar)
`LocationView` é um componente comum: entra direto na tela com `add(LAY_AUTO, ...)`. O construtor declara `throws IOException`, já coberto pelo `onShow() throws Exception`. O timer inicia no `onAdd` e para no `onRemove` — não é preciso gerenciá-lo manualmente.

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

      add(LAY_AUTO, new Label("Coordenadas do GPS:"));

      LocationView gps = new LocationView(1000);   // lê a cada 1 s; throws IOException
      gps.onAction(c -> {}); // disparado a cada leitura periódica (opcional)
      add(LAY_AUTO, gps);
      // O timer inicia no onAdd e para no onRemove automaticamente.
   }
}
```

> 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
LocationView gps = new LocationView(1000);   // lê a cada 1 s; throws IOException
container.add(LAY_AUTO, gps);
// Ao sair da tela, o onRemove já para o timer; ou chame gps.stop().
```

## Construtores
| Construtor | Descrição |
|---|---|
| `LocationView()` | Intervalo de leitura de 2000 ms, `location = null`. `throws IOException`. |
| `LocationView(int readInterval)` | Intervalo custom (ms; mínimo efetivo 100), `location = null`. `throws IOException`. |
| `LocationView(Location location, int readInterval)` | Fonte de GPS explícita + intervalo. `throws IOException`. |

## Propriedades e personalização
| Método / campo | Tipo | O que faz |
|---|---|---|
| `location` | `Location` (campo) | Fonte de dados de GPS; pode ser passada no construtor ou ficar `null`. |
| `stop()` | `void` | Para o timer e chama `location.stop()`. `throws IOException`. |
| `retrieveGPSData()` | `void` | Lê a posição e atualiza os labels (chamado pelo timer). |
| `getAutoHeight()` | `int` | Altura preferida = `font.scaledHeight() * 5 + ingap.height()`. |
| `LocationView.LAT_LOW_SIGNAL` | `String` estático | Texto exibido quando a latitude não pode ser obtida (localizável). |
| `LocationView.LON_LOW_SIGNAL` | `String` estático | Texto exibido quando a longitude não pode ser obtida (localizável). |

## Callbacks e eventos
| Callback | Quando dispara |
|---|---|
| `onAction(Action)` | A cada leitura periódica (`retrieveGPSData()` chama `runActions()`), com ou sem sinal. Use como ponto de notificação de atualização. |

## Estados
- **inicializando**: antes do primeiro fix, mostra "Location Initialising".
- **com sinal**: exibe lat/lon em graus/minutos/segundos, hora do fix (formato 12/24 h vem de `LocaleFormats.is24Hour`), velocidade/direção quando `!= Location.INVALID` e satélites quando `> 0`.
- **sem sinal**: exibe `LAT_LOW_SIGNAL` / `LON_LOW_SIGNAL` e a razão da falha na última linha.
- **ciclo de vida**: o timer inicia em `onAdd` e é parado em `onRemove` (ou por `stop()`), liberando recursos.

### Fonte de GPS explícita + reação a cada atualização
```java
Location fonte = /* obtida da plataforma / dev.crossfly.device */;
LocationView gps = new LocationView(fonte, 1000);
gps.onAction(c -> atualizarStatusBarra());  // disparado a cada leitura
container.add(LAY_AUTO, gps);

// Localizar as mensagens de baixo sinal:
LocationView.LAT_LOW_SIGNAL = "lat: sem sinal";
LocationView.LON_LOW_SIGNAL = "lon: sem sinal";
```

## Boas práticas
- Deixe o ciclo de vida cuidar do timer: adicionar o widget o inicia, removê-lo o para. Chame `stop()` explicitamente só se precisar liberar a `Location` antes.
- Ajuste `readInterval` conforme a necessidade — intervalos menores gastam mais bateria; o mínimo efetivo é 100 ms.

## Erros comuns
- Esquecer o `throws IOException` dos construtores.
- Esperar um mapa: `LocationView` só mostra texto; para visualização use `Map`.
- Assumir a hora local sem timezone: o fix é ajustado pelo offset do fuso via `TimeZone.getDefault().getRawOffset()`.

## Veja também
- Guia da área: [`ui/`](/docs/ui) · Receitas: [`cookbook/`](/docs/cookbook)
- Conceito (i18n, formatos de locale): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`webcontainer`](/docs/ui/widgets/webcontainer)
