feat(cpp/viz): static-plot primitive + tooltips + rotated labels + card compacta
Nuevo primitivo compartido: - cpp/functions/viz/plot_static.h: header-only con flags ImPlotFlags / ImPlotAxisFlags agrupados (NoFrame|NoMenus|NoBoxSelect|NoMouseText + Lock|NoInitialFit|NoHighlight) para visualizacion estatica en dashboards. Lo usan todos los charts de viz/. Charts refactorizados a v1.1 con parametro `height` explicito (rompe el feedback loop con contenedores AutoResizeY que producia vibracion al redimensionar) y ejes pineados con ImPlotCond_Always: - bar_chart v1.2: tooltip al hover (label + valor) + auto-rotacion de labels a 45 cuando no caben horizontalmente (medidos con CalcTextSize vs ancho del plot). Los labels rotados se dibujan manualmente con ImDrawList::PrimQuadUV + ImFontBaked::FindGlyph (API ImGui 1.92+). - pie_chart v1.1: tooltip por slice (detecta cual via atan2 desde centro en sentido CCW matematico, que es como ImPlot dibuja los slices desde angle0=90) con label + valor + porcentaje. Aspect 1:1 mantenido. - line_plot, scatter_plot, histogram v1.1: ejes pineados con limites calculados de min/max + 5% headroom (histogram usa AutoFit por los bins dinamicos, con Lock para bloquear pan/zoom). kpi_card v1.2: card mas compacta — altura 78px (antes 108), font scale 1.4x (antes 1.8x), padding sm (antes md). Apto para densidades altas de KPIs en dashboards. fullscreen_window v0.2: NoScrollbar|NoScrollWithMouse para eliminar el scrollbar fugaz que aparecia cuando el contenido excedia por 1-2px la ventana, reflow de ancho y vibracion visible al redimensionar. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,11 @@ name: bar_chart
|
||||
kind: component
|
||||
lang: cpp
|
||||
domain: viz
|
||||
version: "1.1.0"
|
||||
version: "1.2.0"
|
||||
purity: pure
|
||||
signature: "void bar_chart(const char* title, const char* const* labels, const float* values, int count, float bar_width = 0.67f, float height = 200.0f)"
|
||||
description: "Renderiza un grafico de barras verticales con ImPlot, ejes pineados (Lock + Cond_Always) y altura explicita para evitar feedback loops visuales"
|
||||
tags: [implot, chart, visualization, gpu, bar, locked-axes]
|
||||
description: "Barras verticales ImPlot con ejes pineados, altura explicita, tooltip al hover y auto-rotacion 45 de labels cuando no caben horizontales"
|
||||
tags: [implot, chart, visualization, gpu, bar, tooltip, rotated-labels, locked-axes]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
@@ -21,36 +21,35 @@ file_path: "cpp/functions/viz/bar_chart.cpp"
|
||||
framework: imgui
|
||||
params:
|
||||
- name: title
|
||||
desc: "Titulo del grafico de barras (tambien se usa como id interno del plot)"
|
||||
desc: "Titulo / id interno del plot"
|
||||
- name: labels
|
||||
desc: "Array de etiquetas para el eje X, una por barra"
|
||||
- name: values
|
||||
desc: "Array de valores numericos para la altura de cada barra"
|
||||
desc: "Array de valores numericos (altura de cada barra)"
|
||||
- name: count
|
||||
desc: "Numero de barras (longitud de labels y values)"
|
||||
- name: bar_width
|
||||
desc: "Ancho de cada barra como fraccion del hueco de celda (default 0.67)"
|
||||
- name: height
|
||||
desc: "Altura del plot en pixeles (default 200). Explicita para evitar feedback loops con contenedores AutoResizeY"
|
||||
output: "Renderiza el grafico de barras en el frame ImGui actual con ejes X/Y pineados"
|
||||
desc: "Altura del plot en pixeles (default 200). Explicita para evitar feedback loops con AutoResizeY"
|
||||
output: "Renderiza barras, tooltip al hover con label+valor, y si los labels horizontales no caben los dibuja rotados 45 grados"
|
||||
---
|
||||
|
||||
# bar_chart
|
||||
|
||||
Barras verticales con ImPlot, pensado para dashboards estaticos (resumenes, KPIs). Diseno:
|
||||
Barras verticales ImPlot pensadas para dashboards. Tres cosas no triviales:
|
||||
|
||||
- **Ejes pineados** — `ImPlotCond_Always` + `ImPlotAxisFlags_Lock` + `ImPlotAxisFlags_NoInitialFit`. Sin esto, ImPlot auto-fitea cada frame y las barras oscilan los primeros frames.
|
||||
- **Y max con 15% de headroom** — calculado a partir de `values` una vez, mas estetico que el fit apretado de ImPlot.
|
||||
- **Altura explicita** — `ImVec2(-1, height)` en vez de `ImVec2(-1, 0)`. Dentro de un `dashboard_panel` (BeginChild con AutoResizeY), un height=0 crea un feedback loop: el plot pide espacio al padre, el padre se redimensiona al plot, el plot recalcula y asi. El efecto visual es que las barras se deslizan de lado al abrir la ventana. Con height fija no hay loop.
|
||||
- **Sin inputs** — `ImPlotFlags_NoInputs | NoFrame | NoBoxSelect | NoMouseText`. Pensado para visualizacion, no exploracion.
|
||||
1. **Ejes pineados** — `plot_static::kPlotFlags` + `kAxisFlags` (Lock + NoInitialFit + Cond_Always) con `y_max` pre-calculado + 15% headroom. Sin esto ImPlot auto-fitea cada frame y las barras oscilan.
|
||||
2. **Tooltip** — si `IsPlotHovered()`, detecta la barra bajo el cursor (`round(mouse.x)` con tolerancia `bar_width/2`) y muestra `label` + valor.
|
||||
3. **Labels auto-rotados** — mide la suma de `CalcTextSize(label) + 12px` contra el ancho del plot; si no caben, dibuja los labels rotados 45° manualmente con `ImDrawList::PrimQuadUV` + glyphs del font atlas (`ImFontBaked::FindGlyph` — API ImGui 1.92+). Reserva 48px abajo del plot para los labels rotados. Si caben se usan los ticks horizontales normales de ImPlot.
|
||||
|
||||
Debe llamarse dentro del render callback de `fn::run_app`.
|
||||
Altura explicita (`height`) rompe el feedback loop con contenedores `AutoResizeY` (ver `viz/plot_static.h`).
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```cpp
|
||||
const char* langs[] = {"go", "py", "ts", "sh", "cpp"};
|
||||
float counts[] = {412, 187, 94, 63, 36};
|
||||
bar_chart("Functions by lang", langs, counts, 5); // height por defecto 200
|
||||
bar_chart("Compact", langs, counts, 5, 0.8f, 120.0f); // compacto
|
||||
const char* domains[] = {"core", "finance", "cybersecurity", "datascience", "infra"};
|
||||
float counts[] = {412, 187, 94, 63, 36};
|
||||
bar_chart("##domains", domains, counts, 5); // horizontal si cabe
|
||||
bar_chart("##domains", domains, counts, 5, 0.8f, 240); // rotated si no cabe
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user