# LocationView

> Displays GPS coordinates (lat, lon, fix time, speed, heading) as text, updated periodically.

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

# LocationView

`LocationView` is a widget that **displays** GPS data as text: latitude and longitude (in degrees/minutes/seconds with N/S and E/W suffixes), fix time, speed, heading and number of satellites. It reads periodically from a `Location` (GPS source — COM/Bluetooth/IR port or native APIs) and updates five stacked `Label`s in a `VerticalLayout`.

It does **not draw a map** — it only shows the numbers. To center a map on the device position, use `Map` (see Ch. 25).

> 🟡 · **Package:** `dev.crossfly.ui` · **Extends:** `Component` · **Data source:** `dev.crossfly.device.Location`

## When to use
- Show the device's current coordinates in text (diagnostics, HUD, GPS status screen).
- Have an automatic periodic position reading without writing the timer loop.

## When NOT to use
- Render a map or mark the position visually → use `Map` (Ch. 25).
- Just read the position once in code, with no UI → use the `Location` class directly.

## Appearance
Five lines of text (lat, lon, fix, speed, direction), left-aligned, in a `VerticalLayout`. While there is no data it shows "Location Initialising"; with no signal, it shows the localizable strings `LAT_LOW_SIGNAL` / `LON_LOW_SIGNAL`.

## Complete example (copy, paste and run)
`LocationView` is an ordinary component: it goes straight into the screen with `add(LAY_AUTO, ...)`. The constructor declares `throws IOException`, already covered by `onShow() throws Exception`. The timer starts in `onAdd` and stops in `onRemove` — no need to manage it manually.

```java
package com.exemplo;

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

/** Runnable main screen. Point the launcher (classname) and run: 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);   // reads every 1 s; throws IOException
      gps.onAction(c -> {}); // fired on each periodic read (optional)
      add(LAY_AUTO, gps);
      // The timer starts on onAdd and stops on onRemove automatically.
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## Basic usage
```java
LocationView gps = new LocationView(1000);   // reads every 1 s; throws IOException
container.add(LAY_AUTO, gps);
// When leaving the screen, onRemove already stops the timer; or call gps.stop().
```

## Constructors
| Constructor | Description |
|---|---|
| `LocationView()` | Read interval of 2000 ms, `location = null`. `throws IOException`. |
| `LocationView(int readInterval)` | Custom interval (ms; effective minimum 100), `location = null`. `throws IOException`. |
| `LocationView(Location location, int readInterval)` | Explicit GPS source + interval. `throws IOException`. |

## Properties and customization
| Method / field | Type | What it does |
|---|---|---|
| `location` | `Location` (field) | GPS data source; can be passed in the constructor or stay `null`. |
| `stop()` | `void` | Stops the timer and calls `location.stop()`. `throws IOException`. |
| `retrieveGPSData()` | `void` | Reads the position and updates the labels (called by the timer). |
| `getAutoHeight()` | `int` | Preferred height = `font.scaledHeight() * 5 + ingap.height()`. |
| `LocationView.LAT_LOW_SIGNAL` | static `String` | Text shown when the latitude cannot be obtained (localizable). |
| `LocationView.LON_LOW_SIGNAL` | static `String` | Text shown when the longitude cannot be obtained (localizable). |

## Callbacks and events
| Callback | When it fires |
|---|---|
| `onAction(Action)` | On each periodic reading (`retrieveGPSData()` calls `runActions()`), with or without signal. Use it as an update notification point. |

## States
- **initializing**: before the first fix, shows "Location Initialising".
- **with signal**: shows lat/lon in degrees/minutes/seconds, fix time (12/24 h format comes from `LocaleFormats.is24Hour`), speed/heading when `!= Location.INVALID` and satellites when `> 0`.
- **no signal**: shows `LAT_LOW_SIGNAL` / `LON_LOW_SIGNAL` and the failure reason on the last line.
- **lifecycle**: the timer starts in `onAdd` and is stopped in `onRemove` (or by `stop()`), releasing resources.

### Explicit GPS source + reaction on each update
```java
Location fonte = /* obtained from the platform / dev.crossfly.device */;
LocationView gps = new LocationView(fonte, 1000);
gps.onAction(c -> atualizarStatusBarra());  // fired on each read
container.add(LAY_AUTO, gps);

// Locate the low-signal messages:
LocationView.LAT_LOW_SIGNAL = "lat: sem sinal";
LocationView.LON_LOW_SIGNAL = "lon: sem sinal";
```

## Best practices
- Let the lifecycle handle the timer: adding the widget starts it, removing it stops it. Call `stop()` explicitly only if you need to release the `Location` earlier.
- Adjust `readInterval` as needed — shorter intervals use more battery; the effective minimum is 100 ms.

## Common mistakes
- Forgetting the constructors' `throws IOException`.
- Expecting a map: `LocationView` only shows text; for visualization use `Map`.
- Assuming local time without a timezone: the fix is adjusted by the zone offset via `TimeZone.getDefault().getRawOffset()`.

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (i18n, locale formats): [`concepts/`](/docs/concepts)
- Related components: [`webcontainer`](/docs/ui/widgets/webcontainer)
