# LocationPicker

> Elección de coordenada geográfica en un mapa con GPS, devolviendo latitud y longitud a quien la invoca.

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

# LocationPicker

`LocationPicker` elige una **coordenada geográfica** en un mapa, con rastreo de GPS y pin arrastrable. Sigue el patrón de los pickers (ver [`Picker`](/docs/ui/widgets/picker)) y devuelve un `LatLon`.

> 🔴 · **Paquete:** `dev.crossfly.ui.picker` · **Extiende:** `Picker` · **Hardware:** GPS + mapa

## Cuándo usar
- Recolectar una ubicación (dirección de entrega, punto de interés) en un mapa.

## Apariencia
Barra superior con botones circulares (tipo de mapa Normal/Satélite, volver, confirmar), el mapa (FILL) ocupando el cuerpo, un pin arrastrable con círculo de precisión (verde/rojo según el PDOP) y un rótulo de estado en la base.

## Ejemplo completo (copiar, pegar y ejecutar)
`LocationPicker` abre un mapa a pantalla completa — dispáralo desde un `Button`. El ejemplo reutiliza el uso básico y muestra la coordenada confirmada en un `Label`. `LatLon` viene de `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.*;

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

      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 del constructor (opcional; puede ser null)
               10.0,          // minPdop
               true,          // puede arrastrar el pin
               true,          // alta precisión
               false);        // sin street view

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

> 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
LocationPicker lp = new LocationPicker(
   coord -> Debug.log("Capturado: " + coord.lat + "," + coord.lon),
   10.0,   // minPdop
   true,   // puede arrastrar el pin
   true,   // alta precisión
   false); // sin street view

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

## Constructores
| Constructor | Descripción |
|---|---|
| `LocationPicker(RunnableWith<LatLon> onCapture, double minPdop, boolean canDragPin, boolean highPrecision, boolean streetview)` | Ver parámetros abajo. |

| Parámetro | Tipo | Qué hace |
|---|---|---|
| `onCapture` | `RunnableWith<LatLon>` | Callback con el `LatLon` al confirmar (puede ser `null`). |
| `minPdop` | `double` | PDOP máximo aceptable; el confirmar queda oculto hasta ser alcanzado. |
| `canDragPin` | `boolean` | Permite arrastrar el pin a una ubicación manual. |
| `highPrecision` | `boolean` | Activa el GPS de alta precisión. |
| `streetview` | `boolean` | Habilita street view en el mapa. |

## Callbacks y eventos
| Callback | Cuándo se dispara |
|---|---|
| `onCapture` (constructor) | al confirmar, con el `LatLon` (si `!= null`). |
| `show(onAnswer)` | al cerrar, entrega el `LatLon` confirmado. |

`getAnswer()` devuelve el `LatLon` confirmado, o `null` si se cancela. **Hay dos caminos para el resultado** (el `onCapture` del constructor y el `onAnswer` del `show`) — ambos solo se disparan cuando `answer != null`.

## Estados
- Arrastrar el pin apaga el GPS (`canUpdateGPS = false`), marca "Custom Location" y revela el confirmar.
- El botón confirmar solo aparece cuando la precisión es aceptable (o en desktop, o tras arrastre manual).
- Los recursos (thread GPS, `Location`, mapa) se liberan una sola vez al cerrar.

## Buenas prácticas
- Elige un `minPdop` realista; en mobile el confirmar queda oculto hasta que el GPS lo alcance.
- No reutilices la instancia tras `hide()` — los recursos de GPS/mapa se liberan.

## Errores comunes
- **Que confirmar nunca aparezca** — el GPS no alcanzó `minPdop` y el usuario no arrastró el pin (en desktop aparece de inmediato).
- **Esperar `onAnswer` en la cancelación** — no se dispara (`answer = null`).

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Base del patrón: [`Picker`](/docs/ui/widgets/picker)
