Files
fn_registry/cpp/functions/viz/bar_chart.cpp
T
egutierrez 8e11c5cfce feat(cpp/viz): kpi_card v1.1 + bar_chart v1.1 — contenedor y altura fijas
kpi_card:
- v1.1: envuelve el contenido en BeginChild con surface bg + border +
  radius::md + padding::md (tokens). Replica Mantine Paper withBorder
  radius="md" p="md" usado en @fn_library/kpi_card.tsx.
- Ancho adaptativo via GetContentRegionAvail — requiere contenedor que
  propague ancho constrained (ImGui::BeginTable). dashboard_grid / BeginGroup
  no funcionan porque no constrainen ancho y la card desborda la celda.
- Linea de trend SIEMPRE visible: delta, sparkline, o em dash (text_dim)
  como placeholder, para que un grid de KPIs quede alineado vertical.
- Colores del delta via tokens (success/error) en vez de hardcoded ImVec4.

bar_chart:
- v1.1: altura explicita como parametro (default 200px). Sin esto, ImPlot
  con ImVec2(-1, 0) entra en feedback loop cuando esta dentro de un
  dashboard_panel (BeginChild con AutoResizeY): plot pide espacio -> padre
  se redimensiona -> plot recalcula. Efecto visual: las barras se deslizan
  los primeros frames.
- Ejes blindados: Lock + NoInitialFit + Cond_Always ademas de los flags
  previos. Y max pre-calculado con 15% de headroom.
- Sin inputs (NoInputs|NoFrame|NoBoxSelect|NoMouseText): estos charts son
  de resumen, no de exploracion.

Actualizados los .md correspondientes con el contrato visual + requisitos
de contenedor, para que cualquier dashboard que componga estos primitivos
obtenga el mismo look.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 20:59:51 +02:00

71 lines
2.7 KiB
C++

#include "viz/bar_chart.h"
#include "implot.h"
#include <vector>
namespace {
// Render bars con ejes fijos y tamano de plot explicito. Dos cosas clave:
//
// 1) Limites pineados con ImPlotCond_Always + Lock: ImPlot por defecto
// auto-fitea Y cada frame, lo que provoca oscilacion visual.
//
// 2) Altura explicita (height > 0 -> ImVec2(-1, height)): sin esto, ImPlot
// toma el espacio disponible del contenedor. Si el contenedor es un
// BeginChild con AutoResizeY (como dashboard_panel), aparece un feedback
// loop: plot pide espacio al padre -> padre se redimensiona al plot ->
// plot recalcula -> las barras "se deslizan" en los primeros frames.
template <typename T>
void draw_bars(const char* title, const char* const* labels, const T* values,
int count, double bar_width, float height) {
if (count <= 0) return;
double y_max = 0.0;
for (int i = 0; i < count; i++) {
if (static_cast<double>(values[i]) > y_max) y_max = static_cast<double>(values[i]);
}
if (y_max <= 0.0) y_max = 1.0;
y_max *= 1.15; // 15% headroom sobre la barra mas alta
const ImPlotFlags plot_flags =
ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText
| ImPlotFlags_NoInputs | ImPlotFlags_NoFrame;
const ImPlotAxisFlags x_flags =
ImPlotAxisFlags_NoMenus | ImPlotAxisFlags_Lock
| ImPlotAxisFlags_NoInitialFit | ImPlotAxisFlags_NoGridLines
| ImPlotAxisFlags_NoHighlight;
const ImPlotAxisFlags y_flags =
ImPlotAxisFlags_NoMenus | ImPlotAxisFlags_Lock
| ImPlotAxisFlags_NoInitialFit | ImPlotAxisFlags_NoHighlight;
const ImVec2 plot_size(-1.0f, height > 0.0f ? height : 200.0f);
if (ImPlot::BeginPlot(title, plot_size, plot_flags)) {
std::vector<double> positions(count);
for (int i = 0; i < count; i++) positions[i] = i;
ImPlot::SetupAxes(nullptr, nullptr, x_flags, y_flags);
ImPlot::SetupAxisLimits(ImAxis_X1, -0.5, static_cast<double>(count) - 0.5,
ImPlotCond_Always);
ImPlot::SetupAxisLimits(ImAxis_Y1, 0.0, y_max, ImPlotCond_Always);
ImPlot::SetupAxisTicks(ImAxis_X1, positions.data(), count, labels);
ImPlot::PlotBars("##data", values, count, bar_width);
ImPlot::EndPlot();
}
}
} // namespace
void bar_chart(const char* title, const char* const* labels, const float* values,
int count, float bar_width, float height) {
draw_bars<float>(title, labels, values, count, static_cast<double>(bar_width), height);
}
void bar_chart(const char* title, const char* const* labels, const double* values,
int count, double bar_width, float height) {
draw_bars<double>(title, labels, values, count, bar_width, height);
}