Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
13 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | tested | tests | test_file_path | file_path | params | output | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| data_table | function | cpp | viz | 1.4.0 | impure | void data_table::render(const char* id, const std::vector<TableInput>& tables, State& st, std::vector<TableEvent>* events_out = nullptr, bool show_chrome = true) | Render UI completa de tabla TQL: chips bar, tabla, viz panels, column-stats inline, drill, color rules, joins, TQL editor, Ask AI, Button renderer, event sink (ButtonClick/RowDoubleClick/RowRightClick), tooltip per-cell, column_specs persisted in TQL. Dots renderer para sparkline-like de status (v1.3.0). CategoricalChip (dot izquierda + text, siempre visible) y ColorScale (gradient N-color en fondo de celda) en v1.4.0. Entry-point publica del stack data_table. Muta State segun interaccion del usuario. |
|
|
|
false | error_go_core |
|
true |
|
cpp/tests/test_column_specs.cpp | modules/data_table/data_table.cpp |
|
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. Events emitted via events_out. |
Ejemplo
#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", "actions"};
t.types = {data_table::ColumnType::Int,
data_table::ColumnType::Float,
data_table::ColumnType::String,
data_table::ColumnType::String};
// Phase 2: declarative renderers + tooltip
t.column_specs.resize(4);
t.column_specs[2].renderer = data_table::CellRenderer::Badge;
t.column_specs[2].badges = {{"paid","#22c55e","Paid"},{"pending","#f59e0b",""}};
t.column_specs[2].tooltip = "auto";
t.column_specs[2].tooltip_on_hover = true;
t.column_specs[3].renderer = data_table::CellRenderer::Button;
t.column_specs[3].button_action = "cancel_order";
t.column_specs[3].button_label = "Cancel";
data_table::State st; // persiste entre frames
std::vector<data_table::TableEvent> events;
// --- Render (cada frame) ---
ImGui::Begin("Orders");
ImGui::BeginChild("##tbl", ImVec2(-1, -1));
events.clear();
data_table::render("##orders", {t}, st, &events);
ImGui::EndChild();
ImGui::End();
// --- Process events ---
for (const auto& ev : events) {
if (ev.kind == data_table::TableEventKind::ButtonClick &&
ev.action_id == "cancel_order") {
cancel_order(ev.row); // app handles the action
}
if (ev.kind == data_table::TableEventKind::RowDoubleClick) {
open_order_detail(ev.row);
}
}
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.
Usar CategoricalChip cuando quieras un indicador visual (dot de color) siempre visible a la izquierda del texto de la celda, para columnas categoricas (estado, tipo, severidad). Mas discreto que Badge y sin hover-only. Usar ColorScale cuando la columna sea numerica continua y quieras dar contexto visual de "alto/bajo/medio" con un fondo tintado proporcional al valor — util para latencias, scores, porcentajes, metricas.
Gotchas
- ImGui + ImPlot context activos:
render()llama a APIs de ambas librerias. Llamar fuera de un frame activo causa UB. - State no stack-local:
Statecontiene 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_stageyst.stagesse mutan por click en charts. El caller puede leersttrasrender()para reaccionar. - Thread-safety:
render()usastatic thread_localpara buffers intermedios. Llamar solo desde el main thread de ImGui. - TableInput owner externo:
cellses un puntero raw al array del caller. Los datos deben sobrevivir durante toda la llamada arender(). No pasar puntero a vector que puede reallocarse. - events_out no se limpia:
render()solo hacepush_back. El caller debe llamarevents.clear()antes de cada frame o acumulara eventos de frames anteriores. - Button + celda vacia: si el cell value es vacio, el boton NO se dibuja. La app controla cuando mostrar el boton poniendo un value no vacio (ej. "1" o el ID de la fila).
- RowRightClick emite evento Y abre popup interno: la tabla de stages (stage>0) sigue abriendo su popup de drill. En el raw table (stage 0), se emite el evento pero el popup de drill antiguo tambien puede abrirse via
U.open_cell_popup. El caller puede ignorar el popup interno y gestionar su propio menu al detectarRowRightClick. - CategoricalChip sin regla coincidente → sin dot: si ninguna
ChipRule.matchcoincide con el valor de la celda, solo se renderiza el texto. Definir una regla de fallback explicita si se necesita dot para valores no mapeados. - ColorScale clampa fuera de rango: valores por debajo de
range_minse tratan como t=0 (primer stop) y valores por encima derange_maxcomo t=1 (ultimo stop). Definirrange_min/range_maxsensatos para que el gradiente sea informativo; valores muy alejados de la mayoria hacen que todo el gradiente aparezca en un extremo. - aux_column_specs merge: si
TableInput.column_specsesta vacio peroState.aux_column_specs[0]no,render()los aplica automaticamente. Si el caller pasa column_specs no vacios, ganan sobre los del State. - Ask AI modal (llm_anthropic): el boton "Ask AI" usa un stub interno de
llm_anthropicque retorna error por defecto. Para activar la feature real, compilar con-DFN_LLM_ANTHROPIC=1y proveerinfra/llm_anthropic.hen el include path. Pendiente Wave 4: promover al registry. - FN_TQL_DUCKDB: modo SQL del Ask AI requiere compilar con
-DFN_TQL_DUCKDB=1y la libreria DuckDB disponible.
Notas
No hay tests unitarios directos: render() requiere ImGui + ImPlot context activos (imposible sin ventana GL). Cobertura via:
cpp/apps/primitives_gallery/playground/tables/— playground original con self_test.cpp y e2e_run.sh.- 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.cppcompila sin el playground en el include path. tql::applyfirma extendida ya entql_apply_cpp_core(wave anterior). Resuelto.tql_to_sqlpromovido acore/tql_to_sql.h. Resuelto.data_table_logichelpers (row_to_tsv, drill, view_mode, etc.) declarados comostaticendata_table.cpp. No son API pública.State::ensure_stage0/raw/activeimplementados encompute_stage.cpp.ColStatsstruct: usa el decompute_column_stats_cpp_core. Unificado.
Deuda tecnica restante (Wave 4):
llm_anthropic(Ask AI modal, issue 0080): stub interno activo. Promover acpp/functions/infra/llm_anthropicpara activar feature real.FN_TQL_DUCKDB: modo SQL del Ask AI sin soporte en stub. Requiere DuckDB + flag de compilacion.column_specsTQL 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.
v1.2.0 (2026-05-15) — Button renderer + event sink (ButtonClick/RowDoubleClick/RowRightClick) + tooltip per cell + column_specs persisted in TQL (aux_column_specs roundtrip). Back-compat preserved: events_out=nullptr by default; existing render() callers unchanged.
v1.3.0 (2026-05-15) — Dots renderer for inline status timelines (sparkline-like). Reuses badges for color mapping. dots_max/dots_separator/dots_show_count/dots_glyph_size fields. TQL roundtrip. dag_engine_ui canonical use case (10-col antipattern -> 6-col fix).
v1.3.1 (2026-05-15) — Dots renderer now draws filled circles via ImDrawList instead of Unicode glyph. Font-independent: works regardless of TTF glyph coverage. Closes "dots show as ?" bug in dag_engine_ui.
v1.3.2 (2026-05-15) — Hover dimming: row uses muted alpha (0.05 vs default 0.31); hovered cell gets a subtle overlay (~9% white) via ImDrawList. Badge no longer SpanAllColumns. Closes "table-wide bright highlight on hover".
v1.3.3 (2026-05-15) — Selectable bg disabled for Text/empty cells (was duplicating with manual overlay → gray double-hover). Explicit ImVec2 size on Selectable so empty cells get a hit area (fixes drag-select skipping empties). Single uniform hover layer across all cell renderers.
v1.3.4 (2026-05-15) — Row height tightened: GetTextLineHeight() (no spacing) replaces GetTextLineHeightWithSpacing() in Selectable size + manual overlay rect. Removes inflated row vertical padding introduced in v1.3.3.
v1.3.5 (2026-05-15) — Cell hover paints via TableSetBgColor (covers entire cell bg including CellPadding) instead of manual AddRectFilled inside content area. Hit-test expanded by CellPadding for proper edge-to-edge coverage. Closes "hover has gap between cell borders".
v1.3.6 (2026-05-15) — Selection (drag-range) also paints via TableSetBgColor — same edge-to-edge coverage as hover. Header/HeaderHovered/HeaderActive colors set to fully transparent so Selectable doesn't paint anything; all cell bg states (hover, selected, selected+hover) go through TableSetBgColor uniformly.
v1.4.0 (2026-05-16) — new renderers: CategoricalChip (dot izquierda + text, always visible, replaces hover-only color-on-text for categorical) + ColorScale (continuous N-color LERP gradient for numeric cells, configurable range_min/range_max/range_stops/range_alpha). New types: ChipRule{match,color} + ColorStop{position,color} in data_table_types.h. TQL roundtrip (emit+apply) for both renderers. 4 headless tests added to test_column_specs.cpp.
Promovido desde cpp/apps/primitives_gallery/playground/tables/data_table.{h,cpp} — issue 0081-H.