# ListViewWindow

> Popup modal que envuelve un ListView en una Window para selección en ventana flotante.

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

# ListViewWindow

`ListViewWindow` envuelve un [`ListView`](/docs/ui/widgets/listview) dentro de una `Window` para comportamiento de **popup modal** (selector flotante centrado). En modo `SINGLE`, el toque en un ítem selecciona y **cierra** la ventana; en `MULTIPLE`, el botón "Confirmar" cierra.

La mayoría de los métodos solo **delega** al `ListView` interno (configuración y consulta de selección). Usa `getPanel()` si quieres el `ListView` embebido sin el popup.

> 🟡 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Window` · **Estilo:** `WindowStyle` (vía `selectionWindowStyle()`)

## Cuándo usar
- Elección modal que interrumpe el flujo (menú de acciones, selector de ítem, confirmación de opciones).
- Quieres centrado automático y tamaño relativo a la pantalla sin montar la `Window` a mano.

## Cuándo NO usar
- Lista embebida en una pantalla (no modal) → usa [`ListView`](/docs/ui/widgets/listview) directo (o `getPanel()`).
- Miles de ítems → usa [`VirtualListView`](/docs/ui/widgets/virtuallistview) dentro de una `Window` propia.

## Apariencia
Ventana centrada ocupando una fracción de la pantalla (`widthRatio`/`heightRatio`, default `0.5`/`0.5`), conteniendo el `ListView` (encabezado + ítems desplazables + botón en `MULTIPLE`). El fondo se oscurece según el `WindowStyle`/`Skin`.

## 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());

      // El ListViewWindow es una Window (popup): abre con show(), no entra en el layout.
      Button abrir = new Button("Escolher vibração");
      abrir.onAction(e -> {
         ListViewWindow pm = new ListViewWindow("Vibrar",
            new String[]{"Curto", "Longo", "Padrão"}, ListViewWindow.ItemType.SINGLE);
         pm.onConfirm(c -> System.out.println("idx = " + pm.getSelectedIndex()));
         pm.show();
      });

      add(.9f, abrir);   // el botón que abre el popup entra en el layout
   }
}
```

> 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
// Popup de menú (SINGLE): tocar cierra y reporta el índice
ListViewWindow pm = new ListViewWindow("Vibrar", new String[]{"Curto", "Longo", "Padrão"},
      ListViewWindow.ItemType.SINGLE);
pm.onConfirm(c -> System.out.println("idx = " + pm.getSelectedIndex()));
pm.show();
```

## Constructores
| Constructor | Descripción |
|---|---|
| `ListViewWindow(String[] items, ItemType itemType)` | Popup sin título |
| `ListViewWindow(String title, String[] items, ItemType itemType)` | Popup con título en el encabezado |

`ListViewWindow.ItemType` es un enum **propio** (`SINGLE`, `MULTIPLE`) que convierte internamente a `ListView.ItemType`.

## Propiedades y personalización
| Propiedad / método | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `size(float widthRatio, float heightRatio)` | `ListViewWindow` | `0.5, 0.5` | Tamaño del popup como fracción de la pantalla |
| `getPanel()` | `ListView` | — | Acceso al `ListView` interno |
| `ItemFactory(ItemFactory)` | `ListViewWindow` | `null` | Fábrica de filas personalizadas (nota la inicial **mayúscula**) |
| `computeIdealHeight(int)` | `int` | — | Delega a `panel.computeIdealHeight` |
| `title/confirmText/itemStyle/confirmButtonStyle/headerStyle` | `ListViewWindow` | tema | Delegaciones fluidas al `ListView` |

### Consulta de selección (delegada)
`getSelectedCount()`, `getSelectedIndex()`, `getSelectedText()`, `getSelectedIndices()`, `getSelectedTexts()`, `isSelected(int)`, `getSelectionState()`.

## Callbacks y eventos
| Callback | Cuándo se dispara |
|---|---|
| `onConfirm(Component.Action)` | `SINGLE`: al tocar un ítem (y cierra). `MULTIPLE`: al tocar "Confirmar" (y cierra) |

## Estados
Como toda `Window`: usa `show()` para exhibir y `hide()` para cerrar. El `ListView` interno ya apunta su `closeAction` a `this::hide`, así que la selección cierra el popup automáticamente.

### Popup con fábrica de filas (imagen + label)
```java
Button abrir = new Button("Lista de imagens");
abrir.onAction(e -> {
   ListViewWindow w = new ListViewWindow("Imagens", labels, ListViewWindow.ItemType.SINGLE);
   w.ItemFactory((text, index) -> {
      Image img = new Image(paths[index]);
      ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
      Component row = new Component().style(Styles.component()
         .pressable().ingap(Gap.ofFont(.3f)).autoHeight(Relative.ofFont(3f)));
      row.setLayout(new GridLayout(Position.START, Position.CENTER));
      row.add(.22f, .78f, iv, new Label(text));
      return row;
   });
   w.show();
});
```

### Multi-selección con tamaño personalizado
```java
ListViewWindow w = new ListViewWindow("Tópicos",
      new String[]{"Java", "Kotlin", "Dart"}, ListViewWindow.ItemType.MULTIPLE)
   .size(.7f, .6f)
   .confirmText("OK");
w.onConfirm(c -> System.out.println(w.getSelectedCount() + " marcados"));
w.show();
```

## Buenas prácticas
- Ajusta `size(...)` al contenido — muchos ítems piden un `heightRatio` mayor; pocos, menor.
- Para embeber la misma lista sin popup, llama a `getPanel()` y agrega el `ListView` devuelto a tu layout.

## Errores comunes
- **Confundir `ItemFactory(...)` (método, `I` mayúscula) con el `itemFactory(...)` del `ListView`** — aquí el método fluido comienza con mayúscula por convención de la clase.
- **Usar el enum equivocado** — en `ListViewWindow` pasa `ListViewWindow.ItemType`, no `ListView.ItemType`.

## Ver también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Componentes relacionados: [`ListView`](/docs/ui/widgets/listview) · [ítems de lista](/docs/ui/widgets/list-items)
