data_table: declarative cell renderers Phase 1 (Badge/Progress/Duration/Icon)
Adds TableInput.column_specs sidecar field enabling apps to declare Badge,
Progress, Duration and Icon renderers per column without writing ImGui inline.
Back-compat: apps without column_specs compile and behave identically.
- data_table_types.h: CellRenderer enum, BadgeRule, IconMapEntry, ColumnSpec types
- data_table.cpp: hex_to_imcolor helper, icon_name_to_glyph static map (~30 Tabler icons),
draw_cell_custom dispatcher, integration in Stage-0 and Stage-N cell loops and draw_extra_panel
- Bump version 1.0.0 -> 1.1.0 with capability growth log
- cpp/tests/test_column_specs.cpp: 5 smoke/linker tests (back-compat + 4 renderer types)
- cpp/tests/CMakeLists.txt: register test_column_specs target linked against fn_table_viz
- types/core/{cell_renderer,badge_rule,icon_map_entry,column_spec}.md: registry type mds
- docs/capabilities/data_table_renderers.md: canonical doc with end-to-end examples
- docs/capabilities/INDEX.md: added data-table-renderers group
All tests green: test_column_specs 5/5, test_fn_table_viz_smoke 8/8,
tql_emit 41/41, tql_apply 88/88, Wave-1 tests 8/8.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,16 +14,23 @@ Indice de grupos de capacidades del registry. Cada grupo agrupa >=3 funciones qu
|
||||
|
||||
| Grupo | N | Que cubre |
|
||||
|---|---|---|
|
||||
| [bigquery](bigquery.md) | 26 | _(editar — promovido automaticamente)_ |
|
||||
| [nlp](nlp.md) | 33 | _(editar — promovido automaticamente)_ |
|
||||
| [docker](docker.md) | 38 | _(editar — promovido automaticamente)_ |
|
||||
| [android](android.md) | 37 | _(editar — promovido automaticamente)_ |
|
||||
| [metabase](metabase.md) | 106 | _(editar — promovido automaticamente)_ |
|
||||
| [registry](registry.md) | 17 | Auditoria y monitorizacion del propio registry: copied-code, uses-functions, unused, proposals, telemetria |
|
||||
| [systemd](systemd.md) | 14 | Generar, instalar, restart y status de unit files systemd via SSH (deploys a VPS) |
|
||||
| [ssh](ssh.md) | 19 | Operar hosts remotos via SSH: config, conn, ejecutar comandos, port-forward, deploys con SCP/rsync |
|
||||
| [deploy](deploy.md) | 21 | Deploy completo Go/C++ a VPS o Windows: Docker+Traefik, systemd, rsync, health checks |
|
||||
| [mantine](mantine.md) | 63 | Frontend Mantine v9 + @fn_library: theming, layout, formularios, modales, instalacion |
|
||||
| [bigquery](bigquery.md) | 26 | Operar Google BigQuery via SDK Python: queries, dataset/table CRUD, jobs, schema, exports |
|
||||
| [nlp](nlp.md) | 33 | Extraccion NLP: PDFs, OCR, chunking, GLiNER/GLiREL, dedup, agregacion de entities/relations |
|
||||
| [docker](docker.md) | 38 | Operar Docker desde Go/Bash: build/run/stop, compose, networks, volumes, logs, deploys |
|
||||
| [android](android.md) | 37 | Toolbelt Android desde WSL2: adb, emuladores AVD, APK build/install, Capacitor, logcat |
|
||||
| [metabase](metabase.md) | 106 | Operar Metabase via API REST: auth, cards, dashboards, collections, snippets, permissions |
|
||||
| [doctor](doctor.md) | 11 | Diagnostico read-only del registry: artefactos, servicios, drift, funciones huerfanas |
|
||||
| [notebook](notebook.md) | 5 | Operar Jupyter Lab colaborativo (discover/read/exec/write/kernel) |
|
||||
| [cpp-windows](cpp-windows.md) | 7 | Compilar, desplegar, lanzar y verificar apps C++ en Windows desde WSL2 |
|
||||
| [git](git.md) | 19 | Operaciones git y Gitea: clonar, commit, push/pull, hooks, TBD, webhooks, sync entre PCs |
|
||||
| [playwright](playwright.md) | 6 | E2E browser: launch chromium, login kanban, drag dnd-kit, keyboard sequence, wait predicate, assert class |
|
||||
| [cpp-tables](tql.md) | 9 | Table Query Language C++ puro: filter, group, agg, sort, join, stats, formulas Lua, round-trip emit/apply |
|
||||
| [data-table-renderers](data_table_renderers.md) | 1 | API declarativa de cell renderers para data_table: Badge, Progress, Duration, Icon via TableInput.column_specs |
|
||||
|
||||
## Como anadir grupo
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# 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<ColumnSpec>` 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).
|
||||
Reference in New Issue
Block a user