# LocationView

> Muestra las coordenadas de GPS (lat, lon, hora del fix, velocidad, dirección) como texto, actualizadas periódicamente.

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

# LocationView

`LocationView` es un widget que **muestra** datos de GPS como texto: latitud y longitud (en grados/minutos/segundos con sufijos N/S y E/W), hora del fix, velocidad, dirección y número de satélites. Lee periódicamente de una `Location` (fuente de GPS — puerto COM/Bluetooth/IR o APIs nativas) y actualiza cinco `Label`s apilados en un `VerticalLayout`.

**No dibuja mapa** — solo muestra los números. Para centrar un mapa en la posición del dispositivo, usa `Map` (ver Cap. 25).

> 🟡 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Component` · **Fuente de datos:** `dev.crossfly.device.Location`

## Cuándo usar
- Mostrar las coordenadas actuales del dispositivo en texto (diagnóstico, HUD, pantalla de estado de GPS).
- Tener una lectura periódica automática de posición sin escribir el loop de timer.

## Cuándo NO usar
- Renderizar un mapa o marcar la posición visualmente → usa `Map` (Cap. 25).
- Solo leer la posición una vez en código, sin UI → usa la clase `Location` directamente.

## Apariencia
Cinco líneas de texto (lat, lon, fix, speed, direction), alineadas a la izquierda, en un `VerticalLayout`. Mientras no hay datos muestra "Location Initialising"; sin señal, muestra las strings localizables `LAT_LOW_SIGNAL` / `LON_LOW_SIGNAL`.

## Ejemplo completo (copiar, pegar y ejecutar)
`LocationView` es un componente común: entra directo en la pantalla con `add(LAY_AUTO, ...)`. El constructor declara `throws IOException`, ya cubierto por el `onShow() throws Exception`. El timer inicia en el `onAdd` y para en el `onRemove` — no es necesario gestionarlo manualmente.

```java
package com.exemplo;

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

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: 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);   // lee cada 1 s; throws IOException
      gps.onAction(c -> {}); // disparado en cada lectura periódica (opcional)
      add(LAY_AUTO, gps);
      // El timer inicia en onAdd y se detiene en onRemove automáticamente.
   }
}
```

> Los fragmentos de abajo muestran **solo el núcleo** (lo que va dentro de `onShow()`). Para ejecutar, colócalos en el esqueleto `MainWindow` de arriba.

## Uso básico
```java
LocationView gps = new LocationView(1000);   // lee cada 1 s; throws IOException
container.add(LAY_AUTO, gps);
// Al salir de la pantalla, onRemove ya detiene el timer; o llame a gps.stop().
```

## Constructores
| Constructor | Descripción |
|---|---|
| `LocationView()` | Intervalo de lectura de 2000 ms, `location = null`. `throws IOException`. |
| `LocationView(int readInterval)` | Intervalo custom (ms; mínimo efectivo 100), `location = null`. `throws IOException`. |
| `LocationView(Location location, int readInterval)` | Fuente de GPS explícita + intervalo. `throws IOException`. |

## Propiedades y personalización
| Método / campo | Tipo | Qué hace |
|---|---|---|
| `location` | `Location` (campo) | Fuente de datos de GPS; puede pasarse en el constructor o quedar `null`. |
| `stop()` | `void` | Para el timer y llama a `location.stop()`. `throws IOException`. |
| `retrieveGPSData()` | `void` | Lee la posición y actualiza los labels (llamado por el timer). |
| `getAutoHeight()` | `int` | Altura preferida = `font.scaledHeight() * 5 + ingap.height()`. |
| `LocationView.LAT_LOW_SIGNAL` | `String` estático | Texto mostrado cuando la latitud no puede obtenerse (localizable). |
| `LocationView.LON_LOW_SIGNAL` | `String` estático | Texto mostrado cuando la longitud no puede obtenerse (localizable). |

## Callbacks y eventos
| Callback | Cuándo se dispara |
|---|---|
| `onAction(Action)` | En cada lectura periódica (`retrieveGPSData()` llama a `runActions()`), con o sin señal. Úsalo como punto de notificación de actualización. |

## Estados
- **inicializando**: antes del primer fix, muestra "Location Initialising".
- **con señal**: muestra lat/lon en grados/minutos/segundos, hora del fix (formato 12/24 h viene de `LocaleFormats.is24Hour`), velocidad/dirección cuando `!= Location.INVALID` y satélites cuando `> 0`.
- **sin señal**: muestra `LAT_LOW_SIGNAL` / `LON_LOW_SIGNAL` y la razón de la falla en la última línea.
- **ciclo de vida**: el timer inicia en `onAdd` y se detiene en `onRemove` (o por `stop()`), liberando recursos.

### Fuente de GPS explícita + reacción a cada actualización
```java
Location fonte = /* obtenida de la plataforma / dev.crossfly.device */;
LocationView gps = new LocationView(fonte, 1000);
gps.onAction(c -> atualizarStatusBarra());  // disparado en cada lectura
container.add(LAY_AUTO, gps);

// Localizar los mensajes de señal baja:
LocationView.LAT_LOW_SIGNAL = "lat: sem sinal";
LocationView.LON_LOW_SIGNAL = "lon: sem sinal";
```

## Buenas prácticas
- Deja que el ciclo de vida se encargue del timer: agregar el widget lo inicia, quitarlo lo para. Llama a `stop()` explícitamente solo si necesitas liberar la `Location` antes.
- Ajusta `readInterval` según la necesidad — intervalos menores gastan más batería; el mínimo efectivo es 100 ms.

## Errores comunes
- Olvidar el `throws IOException` de los constructores.
- Esperar un mapa: `LocationView` solo muestra texto; para visualización usa `Map`.
- Asumir la hora local sin timezone: el fix se ajusta por el offset del huso vía `TimeZone.getDefault().getRawOffset()`.

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (i18n, formatos de locale): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`webcontainer`](/docs/ui/widgets/webcontainer)
