# data_table_renderers — declarative cell renderers (v1.1.0) Tag: `cpp-tables` (mismo grupo que TQL; los renderers son parte del stack `data_table`). Extiende `data_table_cpp_viz` con una API declarativa para renderizar columnas con Badge, Progress, Duration e Icon **sin escribir ImGui inline**. Activado via el campo opcional `column_specs` de `TableInput`. Back-compat 100%: apps sin `column_specs` no necesitan cambios. ## Tipos nuevos en `data_table_types.h` | Tipo | Que es | |---|---| | `CellRenderer` | enum class: `Text=0`, `Badge=1`, `Progress=2`, `Duration=3`, `Icon=4` | | `BadgeRule` | value (exact match) + color_hex + label opcional | | `IconMapEntry` | value + icon_name (ej. `"TI_BOLT"`) + color_hex opcional | | `ColumnSpec` | id + renderer + badges / progress fields / duration thresholds / icon_map | | `TableInput::column_specs` | `std::vector` sidecar opcional (size 0 o == cols) | ## Ejemplo canonico: Recent Executions (status Badge + duration Duration) ```cpp #include "viz/data_table.h" #include "core/data_table_types.h" // --- Datos (owner externo) --- static const char* g_exec_cells[] = { "ok", "142", "error", "3850", "ok", "72", "warn", "1100", }; // --- Setup (una vez, en init de la app o antes del loop) --- data_table::TableInput t; t.name = "executions"; t.rows = 4; t.cols = 2; t.cells = g_exec_cells; t.headers = {"status", "duration_ms"}; t.types = {data_table::ColumnType::String, data_table::ColumnType::Float}; // Columna 0: Badge por valor de status data_table::ColumnSpec cs_status; cs_status.id = "status"; cs_status.renderer = data_table::CellRenderer::Badge; cs_status.badges = { data_table::BadgeRule{"ok", "#22c55e", "OK"}, data_table::BadgeRule{"error", "#ef4444", "ERROR"}, data_table::BadgeRule{"warn", "#f59e0b", "WARN"}, }; // Columna 1: Duration con gradiente verde/amarillo/rojo data_table::ColumnSpec cs_dur; cs_dur.id = "duration_ms"; cs_dur.renderer = data_table::CellRenderer::Duration; cs_dur.duration_warn_ms = 500.0f; cs_dur.duration_error_ms = 2000.0f; t.column_specs = {cs_status, cs_dur}; data_table::State st; // persiste entre frames // --- Render loop --- ImGui::Begin("Executions"); ImGui::BeginChild("##exec_tbl", ImVec2(-1, -1)); data_table::render("##exec", {t}, st); ImGui::EndChild(); ImGui::End(); ``` ## Ejemplo: Progress bar + Icon ```cpp data_table::ColumnSpec cs_progress; cs_progress.id = "completion"; cs_progress.renderer = data_table::CellRenderer::Progress; cs_progress.progress_scale_100 = true; // cell value es 0..100 cs_progress.progress_color_hex = "#3b82f6"; // azul; "" -> ImPlot auto data_table::ColumnSpec cs_icon; cs_icon.id = "kind"; cs_icon.renderer = data_table::CellRenderer::Icon; cs_icon.icon_map = { data_table::IconMapEntry{"fn", "TI_BOLT", "#3b82f6"}, data_table::IconMapEntry{"type", "TI_DATABASE", ""}, data_table::IconMapEntry{"app", "TI_SETTINGS", "#6b7280"}, }; t.column_specs = {cs_progress, cs_icon}; ``` ## Iconos soportados en CellRenderer::Icon El lookup es una tabla estatica de ~30 nombres frecuentes: ``` TI_CHECK TI_X TI_ALERT_CIRCLE TI_CIRCLE_DOT TI_CLOCK TI_LOADER TI_BAN TI_PLAYER_PLAY TI_PLAYER_PAUSE TI_PLAYER_STOP TI_DATABASE TI_SETTINGS TI_USER TI_USERS TI_FILE TI_FOLDER TI_REFRESH TI_BOLT TI_INFO_CIRCLE TI_ARROW_UP TI_ARROW_DOWN TI_ARROW_RIGHT TI_ARROW_LEFT TI_DOTS TI_EYE TI_EYE_OFF TI_EDIT TI_TRASH TI_COPY TI_EXTERNAL_LINK ``` Si el `icon_name` no esta en la tabla, la celda se renderiza como texto plano. ## Fronteras - **Solo Column 0..N posicional**: `column_specs[i]` aplica a la columna en posicion `i` del `TableInput` original. No se mapea por nombre (Phase 2). - **No persiste en TQL**: `column_specs` son responsabilidad del caller — se construyen cada frame o en el setup. `tql_emit`/`tql_apply` no los tocan (Phase 2 planificado). - **No implementa Button/TextInput/Custom** (Phase 2-3 separados). - **Stage N (agregado)**: los renderers se aplican por posicion de columna del output agregado — si el breakout cambia el numero de columnas, revisar los indices. ## Gotchas - `column_specs.size()` debe ser 0 (sin specs) o igual a `t.cols`. Mezcla de tamaños puede causar out-of-bounds silencioso (el render hace `c < column_specs.size()` guard, pero es mejor ser expliciito). - `hex_to_imcolor` acepta `"#rrggbb"` o `"rrggbb"`. Alpha siempre 1.0. Sin soporte para `rgba`. - El ColorRule existente de State (`st.color_rules`) sigue funcionando — ambos sistemas coexisten. Si hay conflicto, `column_specs` toma prioridad para el contenido de la celda; `color_rules` pinta el fondo via `TableSetBgColor`. - En el renderer Badge el `Selectable` con background coloreado consume el item para hover/click — la seleccion de rango con drag puede verse afectada visualmente en columnas Badge. ## Notas - Tests: `cpp/tests/test_column_specs.cpp` (5 tests: 1 back-compat + 4 renderer types). Smoke/linker; no requieren ImGui context. - TQL roundtrip pendiente: issue 0081-O (Phase 2).