# Progress

> Progress indicator — determinate bar, infinite animation or spinning icon.

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

# Progress

`Progress` is a progress indicator with **three** mutually exclusive modes, chosen in the constructor (the `mode` field is `final`): determinate bar (known percentage), infinite indeterminate animation, or icon spinning in a loop. The animations start when it is added (`onAdd`, except under test) and stop when it is removed (`onRemove`).

> 🟢 · **Package:** `dev.crossfly.ui` · **Extends:** `Component` · **Style:** `ProgressStyle`

## When to use
- **`DETERMINATE_BAR`**: when there is a known percentage/value to show.
- **`INDETERMINATE`** / **`SPINNING_ICON`**: when the duration is unknown (loading…).

## When NOT to use
- For the user to **choose** a value by dragging → use [`slider`](/docs/ui/widgets/slider).

## Appearance
Depends on the mode (`Progress.Mode`) and, in the indeterminate case, on the `ProgressType`:

| `ProgressType` | Visual |
|---|---|
| `IOS` | circular spinner (iOS style) |
| `FLUTTER` | circular indicator (easeInOut timing) |
| `MATERIAL` | linear Material bar (continuous wrap) |
| `STRIPED` | animated striped bar |

The bar is **horizontal only**; the height is `max(fontHeight * barHeight, 4)`. The colors come from `filledColor`/`emptyColor` of the `ProgressStyle`.

## Complete example (copy, paste and run)
```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

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 1) Determinate bar (0..100) filled at 75%
      Progress barra = new Progress(0f, 100f);
      barra.setValue(75f);
      barra.style(Styles.progress().barHeight(1.5f));
      add(LAY_AUTO, barra);

      // 2) Indeterminate bar (Material) — animates on its own when added
      Progress material = new Progress(ProgressType.MATERIAL);
      material.style(Styles.progress().barHeight(1.5f));
      add(LAY_AUTO, material);

      // 3) Icon spinning in a loop
      Progress spinner = new Progress(new MaterialIcon("autorenew", 48));
      add(LAY_AUTO, spinner);
   }
}
```

> The snippets below show **only the core** (what goes inside `onShow()`). To run them, place them in the `MainWindow` skeleton above.

## Basic usage
```java
Progress barra = new Progress(0f, 100f);                // DETERMINATE_BAR mode
barra.setValue(75f);                                    // 75%
barra.style(Styles.progress().barHeight(1.5f));
container.add(0f, barra);
```

## Constructors
| Constructor | Mode | Description |
|---|---|---|
| `Progress(float min, float max)` | `DETERMINATE_BAR` | Bar proportional to `value` (starts at `min`). |
| `Progress(ProgressType type)` | `INDETERMINATE` | Infinite animation (Material/Flutter/iOS/Striped). |
| `Progress(Icon icon)` | `SPINNING_ICON` | Spins an icon in a continuous loop. |

## Properties and customization
| Property / method | Type | Default | What it does |
|---|---|---|---|
| `setValue(float)` | `Progress` (fluent) | — | **Bar mode**: sets the value (with `clamp`) and recomputes `progress`. |
| `mode` | `Progress.Mode` (field, `final`) | ctor | Operating mode (read). |
| `value` / `min` / `max` | `float` (field) | ctor | State of the determinate bar. |
| `progress` | `float` (field) | — | Normalized progress `[0,1]` (bar). |
| `pivot(int, int)` | `Progress` (fluent) | `-1,-1` | **Icon mode**: rotation pivot (`-1,-1` = auto-center). |

## Callbacks and events
`Progress` is **non-interactive**: it exposes no callbacks. Update the bar by calling `setValue(...)` as the work progresses.

## States
- **DETERMINATE_BAR**: `setValue(v)` performs `clamp` in `[min,max]`, `progress = (value-min)/(max-min)` and `filledW = barW * progress`.
- **INDETERMINATE / SPINNING_ICON**: continuous `LoopAnimation` started in `onAdd`, stopped in `onRemove`.

### The three modes
```java
// Determinate bar 0..50 with 35 filled
Progress bar = new Progress(0f, 50f);
bar.setValue(35f);
bar.style(Styles.progress().barHeight(1.5f));
container.add(0f, bar);

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

// Spinning icon
Progress spinner = new Progress(new MaterialIcon("autorenew", 48));
container.add(0f, spinner);
```

## Best practices
- Use `DETERMINATE_BAR` whenever you know the percentage; reserve the indeterminate one for unknown durations.
- Customize colors via `filledColor`/`emptyColor` of the style instead of subclassing.

## Common mistakes
- Calling `setValue` in indeterminate/spinner mode: it has no useful visual effect (the value only matters in `DETERMINATE_BAR`).
- Expecting a vertical bar or embedded percentage text: the bar is horizontal only and has no prefix/suffix label.

## See also
- Area guide: [`ui/`](/docs/ui) · Recipes: [`cookbook/`](/docs/cookbook)
- Concept (animation and lifecycle): [`concepts/`](/docs/concepts)
- Related components: [`slider`](/docs/ui/widgets/slider)
