# Dropdown

> ComboBox — botón con flecha que abre una lista para elección única.

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

# Dropdown

`Dropdown` es un componente tipo **ComboBox**: un botón con texto + flecha (`expand_more`) que, al tocarse, abre una `ListViewWindow` con la lista de ítems, posicionada arriba o abajo según el espacio disponible. Tras la selección, el texto del botón pasa a mostrar el ítem elegido. Mientras no se selecciona nada, muestra el **placeholder**.

> 🟡 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Button` · **Estilo:** `DropdownStyle`

## Cuándo usar
- Elección **única** dentro de una lista mediana de opciones, ahorrando espacio en la pantalla.
- Cuando el valor seleccionado debe quedar visible tras la elección.

## Cuándo NO usar
- Para 2–3 opciones siempre visibles → usa [`option`](/docs/ui/widgets/option) en [`group`](/docs/ui/widgets/group).

## Apariencia
Texto a la izquierda; la flecha se posiciona según `DropdownStyle.iconPosition`: `START` (pegada al borde izquierdo), `CENTER` (al lado del texto, layout por defecto `TEXT_AT_LEFT` del `Button`) o `END` (pegada al borde derecho). El popup se abre como una ventana blanca de bordes redondeados que se cierra al tocar fuera (`canMove(false).canHide(true)`).

## Ejemplo completo (copiar, pegar y ejecutar)
```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());

      Label saida = new Label("Nada selecionado");
      add(LAY_AUTO, saida);

      String[] itens = {"One", "Two", "Three", "Four", "Five"};
      Dropdown cb = new Dropdown("Selecione...", itens);
      // onSelect se dispara tras confirmar la elección en el popup
      cb.onSelect(e -> saida.setText("Escolhido: " + cb.getSelectedText()
                                     + " (idx " + cb.getSelectedIndex() + ")"));
      add(LAY_AUTO, cb);
   }
}
```

> Los fragmentos siguientes 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
String[] itens = {"One", "Two", "Three", "Four", "Five"};
Dropdown cb = new Dropdown("Selecione...", itens);
cb.onSelect(e -> {
   String escolhido = cb.getSelectedText();
   System.out.println("escolhido: " + escolhido);
});
container.add(.95f, cb);
```

## Constructores
| Constructor | Descripción |
|---|---|
| `Dropdown(String placeholder, String[] items)` | Placeholder + ítems. |
| `Dropdown(String[] items)` | Ítems con placeholder por defecto `"Select..."`. |

## Propiedades y personalización
| Propiedad / método | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `onSelect(Action)` | `Dropdown` (fluido) | — | Callback al confirmar una selección. |
| `popupHeightRatio(float)` | `Dropdown` (fluido) | `0.4` | Altura del popup (0..1 de la pantalla), usada cuando la altura ideal no se mide. |
| `popupWidthRatio(float)` | `Dropdown` (fluido) | `-1` | Anchura del popup (0..1 de la pantalla); negativo = anchura del propio Dropdown. |
| `getSelectedIndex()` | `int` | `-1` | Índice del ítem actual (o `-1`). |
| `getSelectedText()` | `String` | `null` | Texto del ítem actual (o `null`). |
| `setSelectedIndex(int)` | `Dropdown` (fluido) | — | Selecciona programáticamente; índice inválido (ej.: `-1`) → vuelve al placeholder. |

## Callbacks y eventos
| Callback | Cuándo dispara |
|---|---|
| `onSelect(Action)` | **Después** de confirmar una selección en el popup. Usa `getSelectedText()`/`getSelectedIndex()` dentro de él. |

`onTouchUp` hereda del `Button` y agenda `openPopup()` vía `onUI(...)`.

## Estados
- **placeholder**: ningún ítem seleccionado (`selectedIndex == -1`); muestra el texto de placeholder.
- **seleccionado**: `selectedIndex >= 0`; muestra el texto del ítem.
- **pressed**: heredado del `Button` (fundido al presionar).

### Selección programática y limpiar de vuelta al placeholder
```java
String[] numeros = {"One", "Two", "Three"};
Dropdown cb = new Dropdown("", numeros);
cb.onSelect(e -> System.out.println("idx: " + cb.getSelectedIndex()));
container.add(.95f, cb);

cb.setSelectedIndex(1);   // selecciona "Two" programáticamente
cb.setSelectedIndex(-1);  // limpia: vuelve al placeholder
```

## Buenas prácticas
- Lee la elección vía `getSelectedText()`/`getSelectedIndex()` dentro del `onSelect`.
- Usa `setSelectedIndex(-1)` para "resetear" el campo al placeholder (ej.: en un botón "Limpiar").

## Errores comunes
- Pasar `items` nulo: el constructor lo maneja (`new String[0]`), pero el popup **no se abre** si la lista está vacía.
- Esperar multiselección: `Dropdown` es de elección única; para múltiple, usa `ListView` `MULTIPLE`.

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (ventanas y popups): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`option`](/docs/ui/widgets/option) · [`group`](/docs/ui/widgets/group)
