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:
@@ -1,6 +1,7 @@
|
||||
// data_table_types — types compartidos del stack TQL (Table Query Language).
|
||||
// Promovido al registry desde cpp/apps/primitives_gallery/playground/tables/.
|
||||
// Ver issue 0081 + docs/TQL.md. Pure value types + enums.
|
||||
// Issue 0081-N: CellRenderer / ColumnSpec / BadgeRule / IconMapEntry (v1.1.0).
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
@@ -126,7 +127,55 @@ enum class ViewMode {
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class JoinStrategy { Left, Inner, Right, Full };
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CellRenderer: declarative rendering mode per column (issue 0081-N, v1.1.0).
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class CellRenderer : uint8_t {
|
||||
Text = 0, // default — current behavior
|
||||
Badge = 1, // colored badge per-value
|
||||
Progress = 2, // progress bar (0..1 or 0..100)
|
||||
Duration = 3, // milliseconds with color gradient
|
||||
Icon = 4, // icon lookup by value string
|
||||
// Future (Phase 2-3): Button=5, TextInput=6, Custom=7. IDs reserved.
|
||||
};
|
||||
|
||||
// BadgeRule: maps a cell value to a colored badge label.
|
||||
struct BadgeRule {
|
||||
std::string value; // exact match (case-sensitive)
|
||||
std::string color_hex; // "#rrggbb" or "rrggbb"
|
||||
std::string label; // optional visual override; "" -> use value as-is
|
||||
};
|
||||
|
||||
// IconMapEntry: maps a cell value to a Tabler icon macro name + optional color.
|
||||
struct IconMapEntry {
|
||||
std::string value;
|
||||
std::string icon_name; // e.g. "TI_CHECK", "TI_X" — resolved via static map
|
||||
std::string color_hex; // optional; "" -> default text color
|
||||
};
|
||||
|
||||
// ColumnSpec: rendering spec for one column. Indexed by column position.
|
||||
struct ColumnSpec {
|
||||
std::string id; // stable id, used in TQL (future)
|
||||
CellRenderer renderer = CellRenderer::Text;
|
||||
|
||||
// Badge
|
||||
std::vector<BadgeRule> badges;
|
||||
|
||||
// Progress: cell value is float 0..1 (or 0..100 if progress_scale_100 = true)
|
||||
bool progress_scale_100 = false;
|
||||
std::string progress_color_hex; // override bar color; "" -> ImPlot auto
|
||||
|
||||
// Duration: cell value in milliseconds (float); gradient green<warn<yellow<error<red
|
||||
float duration_warn_ms = 1000.0f;
|
||||
float duration_error_ms = 5000.0f;
|
||||
|
||||
// Icon
|
||||
std::vector<IconMapEntry> icon_map;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tabla extra pasada al render() para joins. Owner externo (caller).
|
||||
// ----------------------------------------------------------------------------
|
||||
struct TableInput {
|
||||
std::string name; // identificador estable (matchea Join.source)
|
||||
std::vector<std::string> headers;
|
||||
@@ -134,6 +183,12 @@ struct TableInput {
|
||||
const char* const* cells = nullptr; // row-major, headers.size() cols x rows filas
|
||||
int rows = 0;
|
||||
int cols = 0;
|
||||
|
||||
// NEW (issue 0081-N, v1.1.0): optional declarative renderers per column.
|
||||
// empty -> all columns use default Text rendering (back-compat preserved).
|
||||
// If non-empty, size must equal cols (or be 0 for "no specs").
|
||||
// column_specs are caller-managed; not persisted in TQL yet (Phase 2).
|
||||
std::vector<ColumnSpec> column_specs;
|
||||
};
|
||||
|
||||
// Join clause: une la tabla actual con `source` por las parejas `on`,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,147 @@
|
||||
---
|
||||
name: data_table
|
||||
kind: function
|
||||
lang: cpp
|
||||
domain: viz
|
||||
version: "1.1.0"
|
||||
purity: impure
|
||||
signature: "void data_table::render(const char* id, const std::vector<TableInput>& tables, State& st, bool show_chrome = true)"
|
||||
description: "Render UI completa de tabla TQL: chips bar, tabla, viz panels, column-stats inline, drill, color rules, joins, TQL editor, Ask AI. Entry-point publica del stack data_table. Muta State segun interaccion del usuario."
|
||||
tags: [tables, viz, ui, imgui, tql, cpp-tables]
|
||||
uses_functions:
|
||||
- compute_stage_cpp_core
|
||||
- compute_pipeline_cpp_core
|
||||
- compute_column_stats_cpp_core
|
||||
- auto_detect_type_cpp_core
|
||||
- tql_emit_cpp_core
|
||||
- tql_apply_cpp_core
|
||||
- tql_helpers_cpp_core
|
||||
- tql_to_sql_cpp_core
|
||||
- lua_engine_cpp_core
|
||||
- join_tables_cpp_core
|
||||
- viz_render_cpp_viz
|
||||
uses_types:
|
||||
- data_table_types_cpp_core
|
||||
- ColumnSpec_cpp_core
|
||||
- CellRenderer_cpp_core
|
||||
- BadgeRule_cpp_core
|
||||
- IconMapEntry_cpp_core
|
||||
- TableInput_cpp_core
|
||||
- State_cpp_core
|
||||
- Stage_cpp_core
|
||||
- StageOutput_cpp_core
|
||||
- ViewMode_cpp_viz
|
||||
- ViewConfig_cpp_viz
|
||||
- VizPanel_cpp_viz
|
||||
- Join_cpp_core
|
||||
- Filter_cpp_core
|
||||
- DrillStep_cpp_core
|
||||
- DerivedColumn_cpp_core
|
||||
- Aggregation_cpp_core
|
||||
- SortClause_cpp_core
|
||||
- ColumnType_cpp_core
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports:
|
||||
- imgui.h
|
||||
- app_base.h
|
||||
- core/data_table_types.h
|
||||
- core/lua_engine.h
|
||||
- core/tql_apply.h
|
||||
- core/tql_emit.h
|
||||
- core/tql_helpers.h
|
||||
- core/tql_to_sql.h
|
||||
- core/compute_stage.h
|
||||
- core/compute_pipeline.h
|
||||
- core/compute_column_stats.h
|
||||
- core/auto_detect_type.h
|
||||
- core/join_tables.h
|
||||
- viz/viz_render.h
|
||||
tested: true
|
||||
tests:
|
||||
- "back-compat: TableInput without column_specs does not crash"
|
||||
- "Badge: TableInput with Badge column_spec compiles and links"
|
||||
- "Progress: TableInput with Progress column_spec compiles and links"
|
||||
- "Duration: TableInput with Duration column_spec compiles and links"
|
||||
- "Icon: TableInput with Icon column_spec compiles and links"
|
||||
test_file_path: "cpp/tests/test_column_specs.cpp"
|
||||
file_path: "cpp/functions/viz/data_table.cpp"
|
||||
params:
|
||||
- name: id
|
||||
desc: "ID unico ImGui para esta instancia, ej. '##orders_table'. Debe ser estable entre frames."
|
||||
- name: tables
|
||||
desc: "Lista de TableInput materializadas en memoria. tables[0] es la main por defecto; si State.main_source no-vacio se usa por nombre. Tablas extra se exponen como joinables en la UI de joins."
|
||||
- name: st
|
||||
desc: "Estado mutable completo: pipeline de stages, joins, viz config, ui tweaks. Debe persistir entre frames — no declarar en el stack del frame."
|
||||
- name: show_chrome
|
||||
desc: "Si false, oculta chips bar + breadcrumb por defecto. El usuario puede reactivar con el boton 'Show UI'. El State persiste el override del usuario entre frames."
|
||||
output: "void. Muta st en respuesta a la interaccion del usuario (filtros, breakouts, sorts, drill, joins, viz mode). Los cambios son visibles en st al retornar."
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```cpp
|
||||
#include "viz/data_table.h"
|
||||
#include "core/data_table_types.h"
|
||||
|
||||
// --- Setup (una vez) ---
|
||||
data_table::TableInput t;
|
||||
t.name = "orders";
|
||||
t.rows = num_rows;
|
||||
t.cols = num_cols;
|
||||
t.cells = cells_ptr; // row-major flat array, owner externo
|
||||
t.headers = {"id", "amount", "status"};
|
||||
t.types = {data_table::ColumnType::Int,
|
||||
data_table::ColumnType::Float,
|
||||
data_table::ColumnType::String};
|
||||
|
||||
data_table::State st; // persiste entre frames
|
||||
|
||||
// --- Render (cada frame) ---
|
||||
ImGui::Begin("Orders");
|
||||
ImGui::BeginChild("##tbl", ImVec2(-1, -1));
|
||||
data_table::render("##orders", {t}, st);
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando una app necesita tabla con filtros + agregaciones + viz + joins sobre datos en memoria. Reemplaza `ImGui::BeginTable` inline + toda la logica TQL manual. Sustituye directamente el include del playground (`tables/data_table.h`) cambiando solo el path a `viz/data_table.h`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **ImGui + ImPlot context activos**: `render()` llama a APIs de ambas librerias. Llamar fuera de un frame activo causa UB.
|
||||
- **State no stack-local**: `State` contiene el historial de drill, pipeline de stages, cache de stats y buffers de UI. Declarar en el stack del frame reset todo el estado del usuario en cada frame.
|
||||
- **Drill-down propaga en State**: `st.active_stage` y `st.stages` se mutan por click en charts. El caller puede leer `st` tras `render()` para reaccionar.
|
||||
- **Thread-safety**: `render()` usa `static thread_local` para buffers intermedios. Llamar solo desde el main thread de ImGui.
|
||||
- **TableInput owner externo**: `cells` es un puntero raw al array del caller. Los datos deben sobrevivir durante toda la llamada a `render()`. No pasar puntero a vector que puede reallocarse.
|
||||
- **Ask AI modal (llm_anthropic)**: el boton "Ask AI" usa un stub interno de `llm_anthropic` que retorna error por defecto. Para activar la feature real, compilar con `-DFN_LLM_ANTHROPIC=1` y proveer `infra/llm_anthropic.h` en el include path. Pendiente Wave 4: promover al registry.
|
||||
- **FN_TQL_DUCKDB**: modo SQL del Ask AI requiere compilar con `-DFN_TQL_DUCKDB=1` y la libreria DuckDB disponible.
|
||||
|
||||
## Notas
|
||||
|
||||
No hay tests unitarios directos: `render()` requiere ImGui + ImPlot context activos (imposible sin ventana GL). Cobertura via:
|
||||
1. `cpp/apps/primitives_gallery/playground/tables/` — playground original con self_test.cpp y e2e_run.sh.
|
||||
2. Wave 4: migration self-tests en las apps que migren desde el playground.
|
||||
|
||||
**Estado Wave 3.5 (issue 0081-I):**
|
||||
- Todos los includes del playground (`data_table_logic.h`, `tql.h`, `tql_to_sql.h`) eliminados. `data_table.cpp` compila sin el playground en el include path.
|
||||
- `tql::apply` firma extendida ya en `tql_apply_cpp_core` (wave anterior). Resuelto.
|
||||
- `tql_to_sql` promovido a `core/tql_to_sql.h`. Resuelto.
|
||||
- `data_table_logic` helpers (row_to_tsv, drill, view_mode, etc.) declarados como `static` en `data_table.cpp`. No son API pública.
|
||||
- `State::ensure_stage0/raw/active` implementados en `compute_stage.cpp`.
|
||||
- `ColStats` struct: usa el de `compute_column_stats_cpp_core`. Unificado.
|
||||
|
||||
**Deuda tecnica restante (Wave 4):**
|
||||
- `llm_anthropic` (Ask AI modal, issue 0080): stub interno activo. Promover a `cpp/functions/infra/llm_anthropic` para activar feature real.
|
||||
- `FN_TQL_DUCKDB`: modo SQL del Ask AI sin soporte en stub. Requiere DuckDB + flag de compilacion.
|
||||
- `column_specs` TQL roundtrip (Phase 2): actualmente caller-managed. No persisten en TQL emit/apply. Planificado en issue 0081-O.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
v1.1.0 (2026-05-15) — declarative CellRenderer (Badge/Progress/Duration/Icon) via TableInput.column_specs sidecar. Back-compat preservado: apps existentes sin column_specs siguen funcionando sin cambios.
|
||||
|
||||
---
|
||||
Promovido desde `cpp/apps/primitives_gallery/playground/tables/data_table.{h,cpp}` — issue 0081-H.
|
||||
Reference in New Issue
Block a user