chore: auto-commit (286 archivos)
- .claude/agents/fn-orquestador/SKILL.md - .claude/commands/fn_claude.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - .claude/rules/ids_naming.md - CHANGELOG.md - apps/dag_engine/README.md - apps/dag_engine/api.go - apps/dag_engine/dags_migrated/example.yaml - apps/dag_engine/dags_migrated/example_lineage_tracking.yaml - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
---
|
||||
name: viz_render
|
||||
kind: function
|
||||
lang: cpp
|
||||
domain: viz
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "bool viz::render(const data_table::StageOutput& out, data_table::ViewMode mode, const data_table::ViewConfig& cfg, ImVec2 size = ImVec2(-1,-1), int* clicked_row_out = nullptr)"
|
||||
description: "Dispatcher de visualizaciones ImPlot sobre StageOutput. Cada modo (bar/column/pie/donut/funnel/scatter/bubble/heatmap/line/area/stacked/etc.) elige automaticamente columnas relevantes salvo override desde ViewConfig. Hit-test devuelve clicked_row_out para drill-down en los modos que lo soportan."
|
||||
tags: [tables, viz, implot, tql, cpp-tables, dispatcher, drilldown]
|
||||
uses_functions: []
|
||||
uses_types:
|
||||
- data_table_types_cpp_core
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [imgui, implot]
|
||||
tested: true
|
||||
tests:
|
||||
- "first_numeric_col returns -1 on empty output"
|
||||
- "first_numeric_col returns 0 for all-numeric output"
|
||||
- "first_numeric_col skips string columns"
|
||||
- "first_category_col returns -1 on all-numeric output"
|
||||
- "first_category_col returns first string column"
|
||||
- "extract_numeric returns NaN for unparseable cells"
|
||||
- "extract_numeric returns empty for out-of-range col"
|
||||
- "extract_category returns empty strings for null cells"
|
||||
- "extract_category returns empty for out-of-range col"
|
||||
test_file_path: "cpp/tests/test_viz_render.cpp"
|
||||
file_path: "cpp/functions/viz/viz_render.cpp"
|
||||
framework: imgui
|
||||
params:
|
||||
- name: out
|
||||
desc: "StageOutput del stage activo: headers, types, cells row-major (output de compute_stage o compute_pipeline)"
|
||||
- name: mode
|
||||
desc: "ViewMode a renderizar: Bar, Column, GroupedBar, StackedBar, Line, Area, Stairs, Scatter, Bubble, Histogram, Histogram2D, Heatmap, BoxPlot, Stem, ErrorBars, Pie, Donut, Funnel, Waterfall, KPI, KPIGrid, Candlestick, Radar"
|
||||
- name: cfg
|
||||
desc: "ViewConfig con overrides de auto-detect: x_col, y_cols, cat_col, size_col, primary_color, hist_bins, pie_radius, show_legend, show_markers, locked, fit_request"
|
||||
- name: size
|
||||
desc: "Tamano en pixeles del plot. ImVec2(-1,-1) usa todo el espacio disponible del contenedor ImGui"
|
||||
- name: clicked_row_out
|
||||
desc: "Output param: si != nullptr y el usuario clico un punto drillable, se escribe el indice de row en StageOutput. -1 si no hubo click. Solo activo en: Bar, Column, Pie, Donut, Funnel, Scatter, Bubble, Heatmap"
|
||||
output: "true si el modo fue renderizado correctamente; false si faltan columnas requeridas (se muestra texto de ayuda centrado) o si out esta vacio"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```cpp
|
||||
#include "viz/viz_render.h"
|
||||
|
||||
// Construir StageOutput trivial (3 filas, 2 cols: categoria + numerica)
|
||||
data_table::StageOutput out;
|
||||
out.headers = {"categoria", "valor"};
|
||||
out.types = {data_table::ColumnType::String, data_table::ColumnType::Float};
|
||||
out.rows = 3; out.cols = 2;
|
||||
// Cells row-major: category0, val0, category1, val1, category2, val2
|
||||
static const char* raw[] = {"alfa", "10.0", "beta", "25.5", "gamma", "7.2"};
|
||||
for (auto p : raw) out.cells.push_back(p);
|
||||
|
||||
data_table::ViewConfig cfg;
|
||||
int clicked = -1;
|
||||
bool ok = viz::render(out, data_table::ViewMode::Bar, cfg,
|
||||
ImVec2(-1, 300), &clicked);
|
||||
if (ok && clicked >= 0) {
|
||||
// clicked = indice de row clicado por el usuario
|
||||
}
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando tienes un `StageOutput` (salida de `compute_stage` o `compute_pipeline`) y quieres renderizarlo visualmente en un panel ImGui. El dispatcher elige las columnas correctas automaticamente; usa `ViewConfig` para forzar columnas concretas o cambiar colores/leyenda/zoom.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Requiere contexto ImGui y contexto ImPlot vivos en el hilo actual. Llamar solo desde dentro del loop de render de `fn::run_app` (entre `ImGui::NewFrame()` y `ImGui::Render()`).
|
||||
- El hit-test (`clicked_row_out`) solo esta activo en los modos: Bar, Column, Pie, Donut, Funnel, Scatter, Bubble, Heatmap. En el resto de modos `*clicked_row_out` queda en -1.
|
||||
- Thread-safety: render DEBE llamarse desde el mismo hilo que `ImGui::NewFrame()`. No hay mutex interno.
|
||||
- Para ViewMode::Table la funcion devuelve `false` inmediatamente (la tabla se renderiza con `table_view_cpp_viz`, no con este dispatcher).
|
||||
- `cfg.fit_request` es `mutable`: la funcion lo consume (pone a false) al hacer el fit. Si pasas un `const ViewConfig&` el campo mutado no se propaga al caller salvo que sea el mismo objeto.
|
||||
- Modo Candlestick asume que las 4 primeras columnas numericas son O/H/L/C en ese orden. Modo Radar usa solo la primera fila como poligono.
|
||||
|
||||
## Tests parciales
|
||||
|
||||
`render()` requiere ImPlot context vivo — no se puede ejercitar sin ventana. Los tests de este archivo cubren las funciones helper puras (`first_numeric_col`, `first_category_col`, `extract_numeric`, `extract_category`) que no dependen de ImGui/ImPlot. Smoke real del dispatcher via `primitives_gallery --capture` (golden images, issue 0048).
|
||||
Reference in New Issue
Block a user