# LocationPicker

> Pick a geographic coordinate on a map with GPS, returning latitude and longitude to the caller.

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

# LocationPicker

`LocationPicker` picks a **geographic coordinate** on a map, with GPS tracking and a draggable pin. It follows the picker pattern (see [`Picker`](/docs/ui/widgets/picker)) and returns a `LatLon`.

> 🔴 · **Package:** `dev.crossfly.ui.picker` · **Extends:** `Picker` · **Hardware:** GPS + map

## When to use
- Collect a location (delivery address, point of interest) on a map.

## Appearance
Top bar with circular buttons (map type Normal/Satellite, back, confirm), the map (FILL) filling the body, a draggable pin with an accuracy circle (green/red according to the PDOP) and a status label at the bottom.

## Complete example (copy, paste and run)
`LocationPicker` opens a full-screen map — trigger it from a `Button`. The example reuses the basic usage and shows the confirmed coordinate in a `Label`. `LatLon` comes from `dev.crossfly.map`.

```java
package com.exemplo;

import dev.crossfly.map.LatLon;

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

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

      Label saida = new Label("Nenhuma coordenada");
      add(LAY_AUTO, saida);

      Button escolher = new Button("Escolher local no mapa")
         .onAction(c ->
         {
            LocationPicker lp = new LocationPicker(
               coord -> {},   // onCapture from the constructor (optional; can be null)
               10.0,          // minPdop
               true,          // the pin can be dragged
               true,          // high precision
               false);        // no street view

            lp.show(answer ->
            {
               LatLon ll = (LatLon) answer;
               if (ll != null)
                  saida.setText("Local: " + ll.lat + ", " + ll.lon);
            });
         });
      add(LAY_AUTO, escolher);
   }
}
```

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

## Basic usage
```java
LocationPicker lp = new LocationPicker(
   coord -> Debug.log("Capturado: " + coord.lat + "," + coord.lon),
   10.0,   // minPdop
   true,   // the pin can be dragged
   true,   // high precision
   false); // no street view

lp.show(answer ->
{
   LatLon ll = (LatLon) answer;
   salvarLocal(ll.lat, ll.lon);
});
```

## Constructors
| Constructor | Description |
|---|---|
| `LocationPicker(RunnableWith<LatLon> onCapture, double minPdop, boolean canDragPin, boolean highPrecision, boolean streetview)` | See parameters below. |

| Parameter | Type | What it does |
|---|---|---|
| `onCapture` | `RunnableWith<LatLon>` | Callback with the `LatLon` on confirmation (may be `null`). |
| `minPdop` | `double` | Maximum acceptable PDOP; confirm stays hidden until it is reached. |
| `canDragPin` | `boolean` | Allows dragging the pin to a manual location. |
| `highPrecision` | `boolean` | Turns on high-precision GPS. |
| `streetview` | `boolean` | Enables street view on the map. |

## Callbacks and events
| Callback | When it fires |
|---|---|
| `onCapture` (constructor) | on confirmation, with the `LatLon` (if `!= null`). |
| `show(onAnswer)` | on closing, delivers the confirmed `LatLon`. |

`getAnswer()` returns the confirmed `LatLon`, or `null` if canceled. **There are two paths to the result** (the constructor's `onCapture` and the `show`'s `onAnswer`) — both only fire when `answer != null`.

## States
- Dragging the pin turns off the GPS (`canUpdateGPS = false`), marks "Custom Location" and reveals confirm.
- The confirm button only appears when the accuracy is acceptable (or on desktop, or after a manual drag).
- Resources (GPS thread, `Location`, map) are released exactly once on close.

## Best practices
- Choose a realistic `minPdop`; on mobile the confirm stays hidden until the GPS reaches it.
- Do not reuse the instance after `hide()` — the GPS/map resources are released.

## Common mistakes
- **Confirm never appearing** — GPS did not reach `minPdop` and the user did not drag the pin (on desktop it appears immediately).
- **Expecting `onAnswer` on cancellation** — it does not fire (`answer = null`).

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Pattern base: [`Picker`](/docs/ui/widgets/picker)
