# Como deixar o usuário escolher um local no mapa

> Abrir um mapa com pino arrastável e GPS para o usuário confirmar uma coordenada (LatLon) via LocationPicker.

Source: https://crossfly.dev/pt/docs/cookbook/device/escolher-local-no-mapa — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Como deixar o usuário escolher um local no mapa

**Propósito.** Abrir uma tela de mapa (Google) com **pino arrastável** e rastreamento GPS, para o
usuário confirmar uma posição. O resultado é um `LatLon` entregue por callback.

## APIs usadas
- `LocationPicker(RunnableWith<LatLon> onCapture, double minPdop, boolean canDragPin, boolean highPrecision, boolean streetview)` — construtor completo (é a assinatura real da fonte).
  - `onCapture` — callback chamado com o `LatLon` confirmado (pode ser `null`).
  - `minPdop` — PDOP mínimo aceitável; o botão de confirmar fica oculto até o fix atingir essa precisão (no desktop é sempre liberado).
  - `canDragPin` — `true` para permitir arrastar o pino a uma posição customizada.
  - `highPrecision` — `true` para GPS de alta precisão.
  - `streetview` — `true` para habilitar street view no mapa.
- `LatLon getAnswer()` — posição confirmada, ou `null` se cancelado.
- Estáticos configuráveis: `LocationPicker.defaultZoom`, `Instrucoes`, `GpsLocation`, `CustomLocation`, `Precision`, `Meters`.

> **Divergência vs. a descrição do pedido.** O `LocationPicker` **não** usa `show(onAnswer)` para o
> resultado: a coordenada chega pelo `RunnableWith<LatLon> onCapture` passado no **construtor**
> (e também fica em `getAnswer()`). O `onCapture` só é chamado quando o usuário **confirma** com uma
> posição não-nula. Internamente o picker roda seu **próprio** `GPSThread` (classe interna) e já
> despacha as atualizações via `Component.onUI(...)`, então seu callback executa na paint thread.

## Exemplo completo (copiar, colar e rodar)

```java
package com.exemplo;

import dev.crossfly.ui.*;                   // Window, Button, Label
import dev.crossfly.ui.layout.*;            // VerticalLayout
import dev.crossfly.ui.picker.*;            // LocationPicker
import dev.crossfly.map.*;                  // LatLon
import dev.crossfly.util.*;                 // RunnableWith

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

      Label resultado = new Label("");
      add(LAY_AUTO, resultado);

      Button acao = new Button("Escolher no mapa");
      acao.onAction(c ->
      {
         RunnableWith<LatLon> aoConfirmar = coord ->
         {
            // Já chega na paint thread (o picker usa Component.onUI internamente)
            resultado.setText("Lat " + coord.lat + " / Lon " + coord.lon);
         };

         LocationPicker picker = new LocationPicker(
            aoConfirmar,   // callback com o LatLon confirmado
            30.0,          // minPdop: libera confirmar quando a precisão <= 30m
            true,          // canDragPin: usuário pode arrastar o pino
            true,          // highPrecision
            false);        // streetview
         picker.show();
      });
      add(LAY_AUTO, acao);
   }
}
```

> O trecho abaixo mostra **só o miolo**. Para rodar, coloque-o no esqueleto `MainWindow` acima.

## Trecho mínimo

```java
// verificado na fonte: LocationPicker.java (constructor linhas 129-141, onCapture/closeWith, getAnswer)
import dev.crossfly.ui.picker.*;           // LocationPicker
import dev.crossfly.map.*;                 // LatLon
import dev.crossfly.util.*;                // RunnableWith

RunnableWith<LatLon> aoConfirmar = coord -> {
   // Já chega na paint thread (o picker usa Component.onUI internamente)
   double lat = coord.lat, lon = coord.lon;
   salvarLocal(lat, lon);
};

LocationPicker picker = new LocationPicker(
   aoConfirmar,   // callback com o LatLon confirmado
   30.0,          // minPdop: libera confirmar quando a precisão <= 30m
   true,          // canDragPin: usuário pode arrastar o pino
   true,          // highPrecision
   false);        // streetview
picker.show();

// Alternativa: ler o resultado depois via getAnswer() (null se cancelado)
```

## Aprofunde-se
- Guia de localização: [Location & GPS](/docs/data-and-services/device-location-gps) · Widget: [LocationPicker](/docs/ui/widgets/locationpicker)
- Receita irmã: [obter-gps.md](/docs/cookbook/device/obter-gps)
