# Charts (ChartView)

> Gráficos — línea, área, barra, barra/área apilada, tarta, rosca y combo — con un núcleo de renderizado compartido.

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

# Charts (ChartView + subclases)

El módulo `dev.crossfly.ui.chart` tiene un **núcleo de renderizado compartido** (`ChartView`, que extiende
`Component`) y **8 subclases concretas** que son los puntos de entrada recomendados — cada una
preconfigura el tipo y expone métodos fluidos ergonómicos:

| Clase | Tipo | Cómo añade datos |
|---|---|---|
| `LineChart` | línea | `.withSeries(nome, valores[, cor])` |
| `AreaChart` | línea con área rellena (extiende `LineChart`) | `.withSeries(...)` · `.areaOpacity(int)` |
| `BarChart` | barras agrupadas | `.withSeries(...)` |
| `StackedBarChart` | barras apiladas | `.series(nome, valores[, cor])` |
| `StackedAreaChart` | áreas apiladas (gradiente) | `.series(...)` · `.areaOpacity(int)` |
| `PieChart` | tarta | `.slice(nome, valor[, cor])` |
| `DonutChart` | rosca | `.slice(...)` · `.hole(float)` |
| `ComboChart` | barras + línea (eje Y secundario) | `.addBarSeries(...)` · `.addLineSeries(...)` |

> 🟡 · **Paquete:** `dev.crossfly.ui.chart` · **Extiende:** `Component` · **Estilo:** `ComponentStyle`
>
> ⚠️ **Renombrado 2026:** las antiguas clases `LineChartView`/`BarChartView`/`PieChartView`/
> `DonutChartView`/`ComboChartView` fueron **renombradas** a `LineChart`/`BarChart`/`PieChart`/
> `DonutChart`/`ComboChart` (sufijo `View` eliminado). Y tarta/rosca ahora usan **`slice(...)`** (no
> `withSlice`).

## Cuándo usar
- Tendencias por categoría (línea/área), magnitudes (barra), composición a lo largo del tiempo (apilado),
  proporción de un todo (tarta/rosca), o magnitud + tasa juntas (combo).

## Cuándo NO usar
- Dispersión XY con X arbitrario, 3D o velocímetro → no soportados. Dibujo libre → [`whiteboard`](/docs/ui/widgets/whiteboard).

## Ejemplo completo (copiar, pegar y ejecutar)
En CrossFly escribes **una clase `Window`** (la pantalla principal) — el `Main` y el launcher son
**boilerplate de la plataforma**. Apunta el launcher a esta clase (parámetro `classname`) y ejecuta
`gradlew :lwjgl3:run`:
```java
package com.exemplo;

import dev.crossfly.ui.*;          // Window, Component, LAY_FILL…
import dev.crossfly.ui.layout.*;   // VerticalLayout
import dev.crossfly.ui.chart.*;    // ChartView, LineChart…

/**
 * Pantalla principal ejecutable. Apunte el launcher a esta clase (classname)
 * y ejecute: gradlew :lwjgl3:run
 */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      LineChart line = new LineChart();
      line.withSeries("Revenue", new double[]{42, 55, 51, 68, 73, 88}, 0xFF42A5F5)
          .withSeries("Target",  new double[]{40, 50, 56, 60, 70, 82}, 0xFFAB47BC);
      line.title("Receita por mês");
      line.categories(new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun"});
      line.smooth(true);            // Catmull-Rom
      line.yAxis(0, 100, 5);         // rango Y fijo (o autoYAxis())

      add(LAY_FILL, line);
   }
}
```

> Los fragmentos siguientes muestran **solo el núcleo** (lo que va dentro de `onShow()`), para centrarse en la funcionalidad.
> Para ejecutarlos, coloca el núcleo dentro del esqueleto `MainWindow` de arriba.

## Uso básico (por subclase — recomendado)
```java
LineChart line = new LineChart();
line.withSeries("Revenue", new double[]{42, 55, 51, 68, 73, 88}, 0xFF42A5F5)
    .withSeries("Target",  new double[]{40, 50, 56, 60, 70, 82}, 0xFFAB47BC);
line.title("Receita por mês");
line.categories(new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun"});
line.smooth(true);                       // Catmull-Rom
line.yAxis(0, 100, 5);                    // rango Y fijo (o autoYAxis())
add(LAY_FILL, line);
```

### Barra y barra apilada
```java
BarChart bar = new BarChart();
bar.withSeries("North", new double[]{120, 140, 138, 165}, 0xFF5C6BC0)
   .withSeries("South", new double[]{95, 110, 123, 131}, 0xFF26C6DA);
bar.title("Vendas trimestrais").categories(new String[]{"Q1", "Q2", "Q3", "Q4"});

StackedBarChart stacked = new StackedBarChart();
stacked.series("Direct",  new double[]{6.2, 13.7, 19.9, 8}, 0xFF1976D2)
       .series("Mail Ad", new double[]{18.2, 11, 8, 17.8}, 0xFF81C784);
stacked.yAxis(0, 100, 5);
```

### Área y área apilada
```java
AreaChart area = new AreaChart();
area.withSeries("Load", new double[]{180, 260, 210, 300, 280}, 0xFF26C6DA);
area.areaOpacity(110);                    // alpha 0–255 del relleno

StackedAreaChart sarea = new StackedAreaChart();
sarea.series("Line 1", new double[]{140, 232, 101, 264}, 0xFF6DDB92)
     .series("Line 2", new double[]{120, 282, 111, 234}, 0xFF00D4FF);
sarea.areaOpacity(210);
sarea.decimals = 0;                        // campos públicos para ajuste fino
```

### Tarta y rosca
```java
PieChart pie = new PieChart();
pie.slice("Organic", 38, 0xFF42A5F5)
   .slice("Paid",    24, 0xFFAB47BC)
   .slice("Social",  20, 0xFF26A69A);
pie.title("Fontes de tráfego");

DonutChart donut = new DonutChart();
donut.slice("Organic", 38).slice("Paid", 24).slice("Social", 20)
     .hole(0.58f);                          // radio del agujero [0..0.95]
```

### Combo (barras + línea en eje secundario)
```java
ComboChart combo = new ComboChart();
combo.addBarSeries("Sessions",     new double[]{1000, 1250, 1180, 1340}, 0xFF90CAF9)
     .addLineSeries("Conversion %", new double[]{2.8, 3.1, 2.9, 3.4}, 0xFF1E88E5);  // eje Y derecho
combo.title("Conversão x Sessões").yAxis(0, 1600, 8);
```

## Modelo de datos
- **`ChartView.Series`** (cartesiano): `new Series(nome, double[] valores[, cor])`; los fluidos `.line()` /
  `.bar()` definen el `renderMode` (usado en el combo).
- **`ChartView.PieSlice`** (radial): `new PieSlice(nome, double valor[, cor])`.
- **Color `0` = automático** (paleta `DEFAULT_COLORS`, 9 colores). Para color fijo usa ARGB **con alpha** (`0xFF…`).

## Configuración (campos públicos + fluidos)
| Miembro | Tipo | Por defecto | Qué hace |
|---|---|---|---|
| `title(String)` · `categories(String[])` | fluido | — | título / etiquetas del eje X |
| `yAxis(min, max, steps)` · `autoYAxis()` | fluido | auto | rango del eje Y |
| `smooth(bool)` / `smoothLines` | fluido/campo | `false` | interpolación Catmull-Rom |
| `area(bool)` / `showArea` | fluido/campo | `false` | rellena el área bajo la línea |
| `areaOpacity(int)` / `areaAlpha` | fluido/campo | `0x55` | alpha (0–255) del relleno |
| `showLegend`/`showGrid`/`showTitle`/`showPoints`/`showValues` | campo | `true` | flags de visualización |
| `decimals` | campo | `2` | decimales en etiquetas/tooltips |
| `axisColor`/`axisTextColor`/`legendTextColor`/`gridColor` | campo | tema | colores (ARGB) |
| `pointRadius`/`lineThickness`/`barInnerGap`/`splineSteps` | campo | — | ajuste fino del dibujo |
| `donutHoleRatio` / `hole(float)` | campo/fluido | `0.56` | agujero de la rosca |
| `enableHoverSelection`/`enableInteractionAnimations` | campo | `true` | selección por hover / animación de realce |

> Tras cambiar **campos públicos** fuera de un método fluido, llama a `repaint()`.

## Callbacks y estados
- **`onAction(Action)`** se dispara al **cambiar la selección** (punto/barra/porción) — vía `runActions()`.
  Lee `selectedSeries`+`selectedIndex` (cartesiano) o `selectedSlice` (radial); `-1` = nada.
- Interacción por `onTouchUp` (selecciona el más cercano) y `onHover` (realza bajo el cursor). No hay `onClick`.

## Estilo
Como cualquier `Component`: `chart.getStyle().backColor(...)`/`borderColor(...)`; usa `.copy()` para
derivar sin mutar el compartido:
```java
chart.style(chart.getStyle().copy().backColor(0xFFFFFFFF).borderColor(0xFFE0E0E0));
```

## Buenas prácticas
- Prefiere la **subclase concreta** (`LineChart`, `BarChart`…) al `ChartView` crudo — los métodos fluidos
  son más claros.
- Cartesiano usa `series`/`withSeries`; radial usa `slices`/`slice` — no los mezcles en el mismo tipo.
- Fija `yAxis(min,max,steps)` para ejes estables (el modo automático incluye el cero y puede "aplanar").

## Errores comunes
- Usar los **nombres antiguos** `LineChartView`/`PieChartView`… (renombrados) o **`withSlice`** (ahora `slice`).
- Pasar color `0x00…` esperando negro: `0` es "automático" y alpha `00` es invisible — usa `0xFF000000`.
- Esperar `onClick`: la interacción es vía `onAction` disparado por selección/hover.

## Ver también
- [`ui/`](/docs/ui) · [`cookbook/`](/docs/cookbook) · [`whiteboard`](/docs/ui/widgets/whiteboard)
