feat(views): chart panels con tamano fijo, altura de row constante, gitignore imgui.ini
- Nuevo chart_panel_begin/end local (reemplaza dashboard_panel con AutoResizeY): BeginChild con altura explicita pasada por parametro, NoScrollbar | NoScrollWithMouse. Rompe el feedback loop plot <-> panel que causaba deslizamiento lateral y scrollbar fugaz. - Altura de charts fija 260px (antes GetContentRegionAvail().y * 0.35). Sin esto, redimensionar la ventana propaga cambios de altura a todos los plots y se ve vibracion. - KPIs reorganizados en ImGui::BeginTable 4 cols x 2 rows. Las celdas de tabla propagan ancho constrained, necesario para que el BeginChild interno del kpi_card (card v1.2 compacta 78px) ocupe exactamente la celda. - imgui.ini al .gitignore: estado local de la ventana, no versionable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,3 +2,4 @@ operations.db
|
||||
operations.db-wal
|
||||
operations.db-shm
|
||||
*.exe
|
||||
imgui.ini
|
||||
|
||||
@@ -59,42 +59,93 @@ void draw_kpi_row(const RegistryStats& stats) {
|
||||
}
|
||||
}
|
||||
|
||||
// Chart panel con tamano FIJO (no AutoResizeY) para evitar el feedback loop
|
||||
// con ImPlot que provocaba deslizamiento lateral de las barras y scrollbar
|
||||
// intermitente. Usa los mismos tokens que dashboard_panel para consistencia
|
||||
// visual, pero con tamano determinista.
|
||||
static bool chart_panel_begin(const char* title, const ImVec2& size) {
|
||||
using namespace fn_tokens;
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, colors::surface);
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, colors::border);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, radius::md);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 1.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(spacing::md, spacing::md));
|
||||
|
||||
ImGui::BeginChild(title, size, ImGuiChildFlags_Borders,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, colors::text_muted);
|
||||
ImGui::TextUnformatted(title);
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Separator();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void chart_panel_end() {
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
|
||||
void draw_charts(RegistryData& data, float height) {
|
||||
dashboard_grid_begin(4, 8.0f);
|
||||
// ImGui::BeginTable para reparto equitativo de ancho en 4 columnas y que
|
||||
// cada chart_panel tenga ancho constrained via GetContentRegionAvail.
|
||||
const ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame
|
||||
| ImGuiTableFlags_NoPadOuterX;
|
||||
|
||||
if (dashboard_panel_begin("By Language", 0, height)) {
|
||||
auto labels = to_cstr(data.lang_labels);
|
||||
if (!labels.empty())
|
||||
bar_chart("##lang", labels.data(), data.lang_values.data(), static_cast<int>(labels.size()));
|
||||
// Altura util dentro del panel (height total - title row - separator - padding).
|
||||
// El plot recibe exactamente esto, asi que no hay redimensionado recursivo.
|
||||
const float plot_h = height - 48.0f;
|
||||
|
||||
if (ImGui::BeginTable("##chart_grid", 4, flags)) {
|
||||
ImGui::TableNextRow();
|
||||
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
{
|
||||
ImVec2 sz(ImGui::GetContentRegionAvail().x, height);
|
||||
chart_panel_begin("By Language", sz);
|
||||
auto labels = to_cstr(data.lang_labels);
|
||||
if (!labels.empty())
|
||||
bar_chart("##lang", labels.data(), data.lang_values.data(),
|
||||
static_cast<int>(labels.size()), 0.67f, plot_h);
|
||||
chart_panel_end();
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
{
|
||||
ImVec2 sz(ImGui::GetContentRegionAvail().x, height);
|
||||
chart_panel_begin("By Domain", sz);
|
||||
auto labels = to_cstr(data.domain_labels);
|
||||
if (!labels.empty())
|
||||
bar_chart("##domain", labels.data(), data.domain_values.data(),
|
||||
static_cast<int>(labels.size()), 0.67f, plot_h);
|
||||
chart_panel_end();
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
{
|
||||
ImVec2 sz(ImGui::GetContentRegionAvail().x, height);
|
||||
chart_panel_begin("Purity", sz);
|
||||
const char* labels[] = {"Pure", "Impure"};
|
||||
float values[] = {static_cast<float>(data.stats.pure_functions),
|
||||
static_cast<float>(data.stats.impure_functions)};
|
||||
pie_chart("##purity", labels, values, 2);
|
||||
chart_panel_end();
|
||||
}
|
||||
|
||||
ImGui::TableSetColumnIndex(3);
|
||||
{
|
||||
ImVec2 sz(ImGui::GetContentRegionAvail().x, height);
|
||||
chart_panel_begin("Kind", sz);
|
||||
auto labels = to_cstr(data.kind_labels);
|
||||
if (!labels.empty())
|
||||
pie_chart("##kind", labels.data(), data.kind_values.data(),
|
||||
static_cast<int>(labels.size()));
|
||||
chart_panel_end();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
dashboard_panel_end();
|
||||
dashboard_grid_next();
|
||||
|
||||
if (dashboard_panel_begin("By Domain", 0, height)) {
|
||||
auto labels = to_cstr(data.domain_labels);
|
||||
if (!labels.empty())
|
||||
bar_chart("##domain", labels.data(), data.domain_values.data(), static_cast<int>(labels.size()));
|
||||
}
|
||||
dashboard_panel_end();
|
||||
dashboard_grid_next();
|
||||
|
||||
if (dashboard_panel_begin("Purity", 0, height)) {
|
||||
const char* labels[] = {"Pure", "Impure"};
|
||||
float values[] = {static_cast<float>(data.stats.pure_functions),
|
||||
static_cast<float>(data.stats.impure_functions)};
|
||||
pie_chart("##purity", labels, values, 2);
|
||||
}
|
||||
dashboard_panel_end();
|
||||
dashboard_grid_next();
|
||||
|
||||
if (dashboard_panel_begin("Kind", 0, height)) {
|
||||
auto labels = to_cstr(data.kind_labels);
|
||||
if (!labels.empty())
|
||||
pie_chart("##kind", labels.data(), data.kind_values.data(), static_cast<int>(labels.size()));
|
||||
}
|
||||
dashboard_panel_end();
|
||||
|
||||
dashboard_grid_end();
|
||||
}
|
||||
|
||||
void draw_recent_functions(const std::vector<FunctionRow>& funcs) {
|
||||
@@ -211,11 +262,10 @@ void draw_dashboard(RegistryData& data) {
|
||||
draw_kpi_row(data.stats);
|
||||
ImGui::Dummy(ImVec2(0, fn_tokens::spacing::md));
|
||||
|
||||
// Charts — 35% de la altura restante
|
||||
float remaining = ImGui::GetContentRegionAvail().y;
|
||||
float chart_h = remaining * 0.35f;
|
||||
if (chart_h < 150.0f) chart_h = 150.0f;
|
||||
|
||||
// Charts — altura FIJA en pixeles (no depende del resize de la ventana).
|
||||
// Antes usabamos remaining*0.35, pero eso recalculaba todo el layout al
|
||||
// redimensionar, provocando vibracion visible en los plots.
|
||||
constexpr float chart_h = 260.0f;
|
||||
draw_charts(data, chart_h);
|
||||
ImGui::Dummy(ImVec2(0, fn_tokens::spacing::md));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user