# Progress

> Indicador de progreso — barra determinada, animación infinita o ícono girando.

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

# Progress

`Progress` es un indicador de progreso con **tres modos** mutuamente exclusivos, elegidos en el constructor (el campo `mode` es `final`): barra determinada (porcentaje conocido), animación indeterminada infinita, o ícono girando en bucle. Las animaciones inician al ser añadido (`onAdd`, excepto bajo prueba) y se detienen al ser removido (`onRemove`).

> 🟢 · **Paquete:** `dev.crossfly.ui` · **Extiende:** `Component` · **Estilo:** `ProgressStyle`

## Cuándo usar
- **`DETERMINATE_BAR`**: cuando hay un porcentaje/valor conocido que mostrar.
- **`INDETERMINATE`** / **`SPINNING_ICON`**: cuando la duración es desconocida (cargando…).

## Cuándo NO usar
- Para que el usuario **elija** un valor arrastrando → usa [`slider`](/docs/ui/widgets/slider).

## Apariencia
Depende del modo (`Progress.Mode`) y, en el indeterminado, del `ProgressType`:

| `ProgressType` | Visual |
|---|---|
| `IOS` | spinner circular (estilo iOS) |
| `FLUTTER` | indicador circular (timing easeInOut) |
| `MATERIAL` | barra lineal Material (wrap continuo) |
| `STRIPED` | barra rayada animada |

La barra es **solo horizontal**; la altura es `max(fontHeight * barHeight, 4)`. Los colores vienen de `filledColor`/`emptyColor` del `ProgressStyle`.

## Ejemplo completo (copiar, pegar y ejecutar)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;      // Styles.progress()
import dev.crossfly.ui.graphics.*;   // MaterialIcon

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

      // 1) Barra determinada (0..100) llena al 75%
      Progress barra = new Progress(0f, 100f);
      barra.setValue(75f);
      barra.style(Styles.progress().barHeight(1.5f));
      add(LAY_AUTO, barra);

      // 2) Barra indeterminada (Material) — se anima sola al ser agregada
      Progress material = new Progress(ProgressType.MATERIAL);
      material.style(Styles.progress().barHeight(1.5f));
      add(LAY_AUTO, material);

      // 3) Ícono girando en bucle
      Progress spinner = new Progress(new MaterialIcon("autorenew", 48));
      add(LAY_AUTO, spinner);
   }
}
```

> Los fragmentos de abajo muestran **solo el núcleo** (lo que va dentro de `onShow()`). Para ejecutarlos, colócalos en el esqueleto `MainWindow` de arriba.

## Uso básico
```java
Progress barra = new Progress(0f, 100f);                // modo DETERMINATE_BAR
barra.setValue(75f);                                    // 75%
barra.style(Styles.progress().barHeight(1.5f));
container.add(0f, barra);
```

## Constructores
| Constructor | Modo | Descripción |
|---|---|---|
| `Progress(float min, float max)` | `DETERMINATE_BAR` | Barra proporcional a `value` (inicia en `min`). |
| `Progress(ProgressType type)` | `INDETERMINATE` | Animación infinita (Material/Flutter/iOS/Striped). |
| `Progress(Icon icon)` | `SPINNING_ICON` | Gira un ícono en bucle continuo. |

## Propiedades y personalización
| Propiedad / método | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `setValue(float)` | `Progress` (fluido) | — | **Modo barra**: define el valor (con `clamp`) y recalcula `progress`. |
| `mode` | `Progress.Mode` (campo, `final`) | ctor | Modo de operación (lectura). |
| `value` / `min` / `max` | `float` (campo) | ctor | Estado de la barra determinada. |
| `progress` | `float` (campo) | — | Progreso normalizado `[0,1]` (barra). |
| `pivot(int, int)` | `Progress` (fluido) | `-1,-1` | **Modo ícono**: pivote de rotación (`-1,-1` = auto-centro). |

## Callbacks y eventos
`Progress` es **no interactivo**: no expone callbacks. Actualiza la barra llamando a `setValue(...)` conforme avanza el trabajo.

## Estados
- **DETERMINATE_BAR**: `setValue(v)` hace `clamp` en `[min,max]`, `progress = (value-min)/(max-min)` y `filledW = barW * progress`.
- **INDETERMINATE / SPINNING_ICON**: `LoopAnimation` continua iniciada en `onAdd`, detenida en `onRemove`.

### Los tres modos
```java
// Barra determinada 0..50 con 35 llenado
Progress bar = new Progress(0f, 50f);
bar.setValue(35f);
bar.style(Styles.progress().barHeight(1.5f));
container.add(0f, bar);

// Barra indeterminada (Material)
Progress material = new Progress(ProgressType.MATERIAL);
material.style(Styles.progress().barHeight(1.5f));
container.add(0f, material);

// Ícono girando
Progress spinner = new Progress(new MaterialIcon("autorenew", 48));
container.add(0f, spinner);
```

## Buenas prácticas
- Usa `DETERMINATE_BAR` siempre que conozcas el porcentaje; reserva el indeterminado para duraciones desconocidas.
- Personaliza colores vía `filledColor`/`emptyColor` del estilo en vez de subclasificar.

## Errores comunes
- Llamar a `setValue` en modo indeterminado/spinner: no tiene efecto visual útil (el valor solo importa en `DETERMINATE_BAR`).
- Esperar barra vertical o texto de porcentaje incorporado: la barra es solo horizontal y sin rótulo prefix/suffix.

## Véase también
- Guía del área: [`ui/`](/docs/ui) · Recetas: [`cookbook/`](/docs/cookbook)
- Concepto (animación y ciclo de vida): [`concepts/`](/docs/concepts)
- Componentes relacionados: [`slider`](/docs/ui/widgets/slider)
