Add demos_terminal.cpp con 3 demos del modulo terminal_panel: - Demo 1: one-shot spawn bash, echo hello; date; ls /tmp - Demo 2: terminal interactivo bash/cmd.exe con input box - Demo 3: readonly tail -f con boton append Actualiza CMakeLists.txt con ansi_parser + terminal_panel + -lutil (Linux). Actualiza demos.h + main.cpp con entry "Terminal" en el sidebar. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
primitives_gallery
Catalogo visual interactivo de los primitivos UI del registry (cpp/functions/core y cpp/functions/viz). Un solo ejecutable con sidebar izquierdo + panel derecho que renderiza la demo del primitivo seleccionado con todas sus variantes y un snippet de codigo.
Rol
| Funcion | Como lo cumple |
|---|---|
| Smoke test visual | Abrir la gallery tras un cambio en tokens / componentes; si algo se ve raro, lo cazas en segundos. |
| Documentacion viva | Cada demo muestra el componente trabajando + el snippet exacto. Mas rapido que leer los .md. |
| Build gate | Esta en el CMake principal (cpp/CMakeLists.txt). Si un primitivo rompe API, la gallery no compila => CI rojo. |
| Sandbox de prototipos | Datos sinteticos, sin backend; ideal para iterar un primitivo nuevo sin tocar el dashboard. |
Build & run
# Linux
cmake --build cpp/build/linux --target primitives_gallery -j$(nproc)
./cpp/build/linux/apps/primitives_gallery/primitives_gallery
# Windows (cross-compile)
cmake --build cpp/build/windows --target primitives_gallery -j$(nproc)
# binario: cpp/build/windows/apps/primitives_gallery/primitives_gallery.exe
No se conecta a sqlite_api ni a ningun backend. Datos sinteticos generados in-memory.
Demos disponibles
Core
| Demo | Primitivo | Que muestra |
|---|---|---|
| button | button_cpp_core |
4 variantes x 3 sizes |
| icon_button | icon_button_cpp_core |
Glyphs comunes con tooltip |
| toolbar | toolbar_cpp_core |
Dos grupos con separador vertical |
| modal_dialog | modal_dialog_cpp_core |
Boton que abre modal con form |
| text_input | text_input_cpp_core |
3 inputs con placeholder |
| select | select_cpp_core |
Dropdown con y sin (none) |
| toast + inbox | toast_cpp_core (v1.1) |
4 botones que disparan toasts + campana con badge |
| tree_view | tree_view_cpp_core |
Arbol fake de proyectos -> apps |
| badge | badge_cpp_core |
6 variantes semanticas |
| empty_state | empty_state_cpp_core |
Lista vacia con icono + cta |
| page_header | page_header_cpp_core |
Header con toolbar a la derecha |
| dashboard_panel | dashboard_panel_cpp_core |
Panel con titulo y borde |
| kpi_card | kpi_card_cpp_viz (v1.2) |
Grid 1x4 con sparklines y delta |
Viz
| Demo | Primitivo | Que muestra |
|---|---|---|
| bar_chart | bar_chart_cpp_viz (v1.2) |
Labels que caben + labels rotados 45 |
| pie_chart | pie_chart_cpp_viz (v1.1) |
Pie + donut con tooltip por slice |
| line_plot | line_plot_cpp_viz (v1.1) |
Serie sintetica sin(t) + ruido |
| scatter_plot | scatter_plot_cpp_viz (v1.1) |
120 puntos con correlacion |
| histogram | histogram_cpp_viz (v1.1) |
300 muestras gaussianas |
| sparkline | sparkline_cpp_viz |
Trending up / down / flat |
| graph_viewport | graph_viewport_cpp_viz |
Ver seccion abajo |
Demo graph_viewport (en detalle)
Pipeline completo de visualizacion de grafos con instanced GPU rendering:
graph_renderer_cpp_viz(1 draw call para todos los nodos viaglDrawArraysInstanced)graph_force_layout_cpp_viz(Barnes-Hut, paso de simulacion por frame)graph_spatial_hash_cpp_core(hit-testing O(1) bajo el cursor)graph_viewport_cpp_viz(widget que orquesta los anteriores con pan/zoom/select)
Controles
| Control | Rango | Efecto |
|---|---|---|
Nodes |
100 – 20 000 | Numero de nodos a generar |
Clusters |
2 – 16 | Numero de comunidades (cada una con su color) |
Repulsion |
100 – 20 000 | Fuerza repulsiva entre todos los nodos. Mas alto => grafo mas extendido y energia mayor. |
Attraction |
0.001 – 0.5 | Constante del muelle de las aristas. Mas alto => clusters mas compactos. |
Gravity |
0.0 – 0.05 | Tiron hacia (0,0). Util para evitar drift cuando subes mucho la repulsion. |
Regenerate |
boton | Regenera el grafo con los valores actuales de Nodes/Clusters. |
Pause / Resume layout |
boton | Para o reanuda la simulacion force-directed. |
Fit view |
boton | Encuadra la camara al bounding box del grafo con 10% de padding. |
Los tres sliders de fuerzas se leen cada frame y se inyectan en ForceLayoutConfig, asi que cambiar un valor durante el layout en marcha re-calibra el sistema al instante.
Stats line (sin vibracion)
Una sola linea fija — sin secciones condicionales que cambien la altura del panel:
nodes=N edges=E energy=X fps=F | hover=#id cN sel=#id
hover y sel muestran - cuando no hay nada seleccionado para mantener el ancho/alto estable; antes una fila condicional desplazaba el viewport en cada hover.
Interaccion con el viewport
| Gesto | Accion |
|---|---|
| Drag con boton izquierdo en zona vacia | Pan de camara |
| Wheel | Zoom (limites 0.01x – 50x) |
| Drag sobre nodo | Mueve el nodo (lo pinea durante el drag) |
| Click sobre nodo | Selecciona (s_state.selected_node) |
| Hover sobre nodo | Resaltado + s_state.hovered_node poblado |
Datos sinteticos
generate_synthetic_graph(N, K) reparte N nodos en K clusters dispuestos en circulo, con ~3 aristas intra-cluster por nodo y un 5% adicional de aristas inter-cluster. Paleta de 8 colores ABGR. Posiciones iniciales con dispersion gaussiana de 80 px alrededor del centroide del cluster — el force layout las reordena en pocos frames.
Performance esperada
| Nodes | FPS objetivo (RTX 30xx, viewport 800x460) | Notas |
|---|---|---|
| 1 000 | 60 (vsync) | Caso comun; layout converge < 1 s |
| 5 000 | 60 | Pipeline al limite del CPU para Barnes-Hut |
| 20 000 | 30 – 50 | El cuello pasa a ser el layout (CPU); GPU render sigue holgado |
Si necesitas mas, fija los nodos (pinned = true o Pause layout) y veras 60 fps estables — el bottleneck es la simulacion, no el render.
Anadir un demo nuevo
- Anadir el prototipo en
demos.hdentro denamespace gallery:void demo_my_thing(); - Implementar el cuerpo en
demos_core.cppodemos_viz.cpp(o un fichero nuevo si la demo es grande, p.ej.demos_graph.cpp). - Registrar la entrada en el array
k_demos[]demain.cpp:{"my_thing", "my_thing", "Core" /* o "Viz" */, &gallery::demo_my_thing}, - Si la demo necesita
.cppadicionales del registry, anadirlos aCMakeLists.txtde la gallery. - Recompilar.
Estructura
cpp/apps/primitives_gallery/
CMakeLists.txt # target primitives_gallery
README.md # este fichero
main.cpp # sidebar + router
demo.{h,cpp} # helpers (demo_header, section, code_block, ...)
demos.h # prototipos void demo_xxx()
demos_core.cpp # demos del dominio core
demos_viz.cpp # demos del dominio viz (charts simples)
demos_graph.cpp # demo de graph_viewport (mas pesada, fichero aparte)
Convenciones para los demos
- Sin estado real: usar arrays sinteticos (
float fake[] = {...}) o generadores deterministas con seed fijo. Datos reproducibles. - Sin red: nunca llamar a
sqlite_api, HTTP, filesystem. La gallery debe arrancar offline en cualquier maquina. - Snippets honestos: el
code_block(...)debe mostrar el codigo que produce esa demo, no pseudocodigo. - Variantes en grids: si un primitivo tiene N variantes x M tamanos, mostrarlos todos en un
BeginTablepara comparacion lado-a-lado. - Estado static: si la demo es interactiva (sliders, modal, etc.), guardar el estado en
staticlocales — la gallery no destruye demos al cambiar de seccion, asi que el estado persiste hasta cerrar la app.
Iconos en los demos
A partir de la sesion 2026-04-25 los demos usan los macros TI_* de cpp/functions/core/icons_tabler.h (Tabler v3.41.1, 5093 glyphs). La fuente la carga automaticamente fn::run_app via icon_font_cpp_core, y add_imgui_app copia tabler-icons.ttf junto al ejecutable post-build (no hay paso manual).
demo_icon_button y demo_toolbar (en demos_core.cpp) son la referencia visual: muestran el patron button(TI_PLUS " New", V::Primary) y la fila de iconos sueltos. Ver cpp/DESIGN_SYSTEM.md seccion 11 para la regla.
Si añades un demo nuevo y necesitas glyphs, no metas \x.. UTF-8 inline — busca el icono en icons_tabler.h (o en https://tabler.io/icons) y usa el TI_* correspondiente.