Files
fn_registry/cpp/functions/viz/data_table.md
T
egutierrez 0b9af8f1bb data_table v1.3.1: Dots renderer via ImDrawList (font-independent) + recompile all apps with fn_table_viz (issue 0081-O.6)
- Replace TextColored+glyph with ImDrawList::AddCircleFilled in CellRenderer::Dots.
  Dots are now font-independent: no dependency on Unicode glyph coverage. Fixes
  "dots show as ?" on Karla/Roboto/Inter fonts that lack Geometric Shapes block.
- dots_glyph_size now controls circle radius (px) instead of font scale.
- BadgeRule.label is ignored for Dots (documented in data_table_types.h + docs).
- data_table.md bumped to v1.3.1 with capability growth log entry.
- docs/capabilities/data_table_renderers.md: Dots section updated + Common pitfalls
  entry added: "Asumir que cualquier glyph Unicode renderea".
- dag_engine_ui/tabs.cpp: removed stale "● glyph" comment from BadgeRule.
- Recompiled: dag_engine_ui, registry_dashboard, graph_explorer, navegator_dashboard,
  odr_console. All 5 apps deployed to Desktop/apps/. Build Linux + tests 4/4 green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 17:35:22 +02:00

10 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.3.1 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). Entry-point publica del stack data_table. Muta State segun interaccion del usuario.
tables
viz
ui
imgui
tql
cpp-tables
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
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
TableEvent_cpp_core
TableEventKind_cpp_core
false error_go_core
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
true
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
Button: TableEvent struct constructible; render() with events_out links
Tooltip: ColumnSpec with tooltip_on_hover=true compiles and links
Back-compat: both render() signatures (with/without events_out) link
Dots: ColumnSpec with CellRenderer::Dots + badges constructs correctly
Dots TQL roundtrip: State::aux_column_specs accepts Dots spec
cpp/tests/test_column_specs.cpp cpp/functions/viz/data_table.cpp
name desc
id ID unico ImGui para esta instancia, ej. '##orders_table'. Debe ser estable entre frames.
name desc
tables 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 desc
st Estado mutable completo: pipeline de stages, joins, viz config, ui tweaks, aux_column_specs (Phase 2). Debe persistir entre frames — no declarar en el stack del frame.
name desc
events_out Puntero a vector de TableEvent. Si non-null, se puebla con eventos de este frame (ButtonClick, RowDoubleClick, RowRightClick). El caller limpia/lee el vector despues de cada render. Pasar nullptr para desactivar (back-compat).
name desc
show_chrome 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.
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.

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.
  • events_out no se limpia: render() solo hace push_back. El caller debe llamar events.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 detectar RowRightClick.
  • aux_column_specs merge: si TableInput.column_specs esta vacio pero State.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_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.

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.


Promovido desde cpp/apps/primitives_gallery/playground/tables/data_table.{h,cpp} — issue 0081-H.