---
name: data_table_grid
kind: function
lang: cpp
domain: viz
version: "1.0.0"
purity: impure
signature: "void data_table::render_grid_stage0(const char* id, State& st, const char* const* cells, int row_count, int orig_cols, int eff_cols, const char* const* eff_headers, const ColumnType* eff_types, const int* src_for_eff, const std::vector<int>& visible_rows, const TableInput& main_t, std::vector<TableEvent>* events_out)"
description: "Render del grid de datos de la tabla TQL: ImGui::BeginTable con freeze de cabecera, headers clicables (sort), drag-drop de columnas para reordenar, renderers declarativos por ColumnSpec (Badge/Progress/Duration/Icon/Button/Dots/CategoricalChip/ColorScale), aplicacion de ColorRules por celda, seleccion de rango (Ctrl+C TSV), stats overlay en encabezados. Dos entrypoints: render_grid_stage0 (datos crudos + derived Lua) y render_grid_stage_n (output materializado de compute_stage). Sub-funcion extraida de modules/data_table/data_table.cpp (issue 0107c)."
tags: [viz, table, imgui, ui, grid, cell-renderer, sorting, tql, cpp-tables]
uses_functions:
  - data_table_color_rules_cpp_viz
  - data_table_cpp_viz
uses_types:
  - data_table_types_cpp_core
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [imgui]
tested: false
tests: []
test_file_path: ""
file_path: "cpp/functions/viz/data_table_grid.cpp"
framework: imgui
params:
  - name: id
    desc: "ID unico de ImGui para BeginTable (ej. '##my_table'). Debe ser unico por instancia en la ventana."
  - name: st
    desc: "State mutable. El grid lee st.col_order, st.col_visible, st.color_rules, st.sel_anchor/end, st.stages[active].sorts. Lo muta en respuesta a clicks, drag-drop, seleccion."
  - name: cells
    desc: "Puntero a cells originales row-major [rows * orig_cols]. Para stage0; stage_n recibe cur_cells ya materializados."
  - name: row_count / orig_cols / eff_cols
    desc: "Dimensiones de la tabla. orig_cols = columnas del input; eff_cols = orig_cols + derived cols del stage 0."
  - name: eff_headers / eff_types
    desc: "Headers y tipos efectivos (size eff_cols). Usados para headers del BeginTable y para render de celda."
  - name: src_for_eff
    desc: "Mapeo eff_col_idx -> src_col_idx en la tabla original. Necesario para leer cells[row * orig_cols + src]. Solo para stage0."
  - name: visible_rows
    desc: "Indices de filas visibles tras filtrado (output de compute_visible_rows). Solo para stage0."
  - name: main_t
    desc: "TableInput principal: proporciona column_specs para draw_cell_custom y los column_spec ids para eventos."
  - name: events_out
    desc: "Si no null, recibe TableEvent (ButtonClick, RowDoubleClick, RowRightClick) generados este frame."
output: "Void. Mutates st (sort, selection, col_order). Appends to events_out si no null."
---

## Documentacion

Sub-funcion que encapsula el render del grid de celdas de la tabla TQL. Es el bloque mas grande del refactor 0107c (~1300 LOC del fuente original).

### Renderers declarativos (draw_cell_custom)

| Renderer | Que muestra |
|---|---|
| `Text` | Selectable de texto, tooltip on-hover si `tooltip_on_hover=true` |
| `Badge` | Pastilla de color (background del spec) con texto |
| `Progress` | Barra de progreso ImGui [0..100] |
| `Duration` | Formato "Xh Ym Zs" desde segundos enteros |
| `Icon` | Glyph Tabler (usa `icons_tabler.h`) |
| `Button` | Boton clickable; emite `TableEventKind::ButtonClick` con `action_id` |
| `Dots` | Circulos coloreados por reglas de chips del ColumnSpec |
| `CategoricalChip` | Pastilla con borde coloreado; color por palette hash |
| `ColorScale` | Degradado de fondo segun valor numerico normalizado |

### Flujo render_grid_stage0

1. Setup `ImGuiTableFlags` (Borders + RowBg + Resizable + ScrollY).
2. `BeginTable` → `TableSetupColumn` por cada col visible en `st.col_order`.
3. `TableSetupScrollFreeze(0, 1)` para freeze de header.
4. Header row: `Selectable` con sort-click (`apply_header_sort_click`), drag-drop source/target para reordenar columnas.
5. Por cada fila en `visible_rows`: por cada col visible en `st.col_order`: `apply_color_rules_for_cell` → `draw_cell_custom`.
6. Seleccion de rango: mouse drag con `sel_anchor/sel_end`; Ctrl+C genera TSV al portapapeles.
7. `EndTable` + `PopStyleColor(3)`.

### Flujo render_grid_stage_n

Igual pero opera sobre `cur_cells` ya materializados del chain `compute_stage`. Ademas:
- Stats overlay en headers (histograma/top-categories de `st.stats_cache`).
- Drill popup: right-click en celda de breakout col ofrece "Drill into: col = val".

## Ejemplo

```cpp
// Dentro del render() principal, path stage == 0:
if (st.display == data_table::ViewMode::Table && visible_cols > 0) {
    data_table::render_grid_stage0(id, st,
        cells_in, row_count_in, orig_cols, eff_cols,
        eff_headers.data(), eff_types.data(), src_for_eff.data(),
        visible_rows, main_t, events_out);
}
```

## Cuando usarla

Llamar desde el entrypoint thin `data_table::render()` tras calcular `visible_rows` (stage 0) o materializar el chain (stage > 0). No llamar directamente desde apps — la API publica es `data_table::render()`.

## Gotchas

- `render_grid_stage0` y `render_grid_stage_n` deben llamarse dentro de un `ImGui::BeginChild` o contexto de ventana activo. No funcionan fuera de un frame ImGui.
- La funcion hace `PushStyleColor` para Header/HeaderHovered/HeaderActive y debe hacer el correspondiente `PopStyleColor(3)`. No anidar pushes adicionales sin su pop.
- `draw_cell_custom` con renderer `Button` emite eventos; si `events_out` es null se ignoran silenciosamente (back-compat).
- El `thread_local` en el entrypoint original (main_hdr_ptrs, joinables_v) no se mueve a esta funcion — esos son responsabilidad del entrypoint thin.
- Despues del split, `apply_color_rules_for_cell` vive en `data_table_color_rules_cpp_viz` — no re-implementar aqui.
