Files
tables_qa/tab_compat.cpp
egutierrez b15106fc09 chore: auto-commit (23 archivos)
- CMakeLists.txt
- app.md
- appicon.ico
- main.cpp
- perf_tests.cpp
- perf_tests.h
- qa_panel.cpp
- qa_panel.h
- qa_state.cpp
- qa_state.h
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:31:32 +02:00

297 lines
11 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// tab_compat — Version selector + side-by-side rendering (simulación educativa).
// Muestra la MISMA TableInput renderizada dos veces con distinta ColumnSpec config:
// Left panel : full renderers (v2.1 current).
// Right panel : renderers degradados según la versión simulada seleccionada.
//
// Issue 0108 fase 2. Patrón: tab_renderers.cpp.
// NOTA: esto es una SIMULACIÓN educativa del compat mode futuro.
// El compat real requiere flag en el módulo (TBD issue futuro).
#include "tabs.h"
#include "qa_state.h"
#include "data_table/data_table.h"
#include <imgui.h>
#include <string>
#include <vector>
namespace tables_qa::tabs {
namespace {
// ---------------------------------------------------------------------------
// Datos: 8 filas × 5 cols (id, name, status, duration_ms, priority).
// ---------------------------------------------------------------------------
qa::TabState g_left; // panel izquierdo — full config v2.1
qa::TabState g_right; // panel derecho — config degradada
static const char* k_headers[] = { "id", "name", "status", "duration_ms", "priority" };
static const int k_cols = 5;
static const int k_rows = 8;
// backing strings: row-major id/name/status/duration_ms/priority
static const char* k_cells_raw[k_rows * k_cols] = {
"1", "auth_service", "ok", "320", "high",
"2", "db_sync", "error", "4800", "critical",
"3", "cache_warmup", "running", "750", "medium",
"4", "report_gen", "pending", "2100", "low",
"5", "email_dispatch", "ok", "180", "high",
"6", "index_rebuild", "error", "5900", "critical",
"7", "metrics_collector", "running", "950", "medium",
"8", "snapshot_export", "pending", "1500", "low",
};
// ---------------------------------------------------------------------------
// Versiones simuladas
// ---------------------------------------------------------------------------
enum class SimVersion {
V21 = 0, // v2.1.0 — full renderers
V20 = 1, // v2.0.0 — full renderers, solo split refactor
V15 = 2, // v1.5.0 — no CategoricalChip → fallback Text en status
V14 = 3, // v1.4.0 — no Dots, no CategoricalChip, no ColorScale → Badge básico
};
static const char* k_version_labels[] = {
"v2.1.0 (current)",
"v2.0.0 (split refactor, MODE: no renderer config)",
"v1.5.0 (legacy, MODE: no CategoricalChip)",
"v1.4.0 (legacy, MODE: no Dots + no ColorScale)",
};
static int g_selected_version = 0;
// ---------------------------------------------------------------------------
// Construir TableInput — cabeceras + tipos + punteros a datos estáticos.
// ColumnSpec se rellena por cada panel por separado.
// ---------------------------------------------------------------------------
static data_table::TableInput make_base_table(const char* tbl_name) {
data_table::TableInput t;
t.name = tbl_name;
t.headers = { "id", "name", "status", "duration_ms", "priority" };
t.types = {
data_table::ColumnType::Int,
data_table::ColumnType::String,
data_table::ColumnType::String,
data_table::ColumnType::Float,
data_table::ColumnType::String,
};
t.cells = k_cells_raw;
t.rows = k_rows;
t.cols = k_cols;
return t;
}
// Specifica las reglas de CategoricalChip para la col status
static void apply_status_chip(data_table::ColumnSpec& cs) {
cs.renderer = data_table::CellRenderer::CategoricalChip;
cs.chips = {
{ "ok", "#22c55e" },
{ "error", "#ef4444" },
{ "running", "#f59e0b" },
{ "pending", "#a3a3a3" },
};
}
// Specifica Badge básico (fallback sin CategoricalChip)
static void apply_status_badge(data_table::ColumnSpec& cs) {
cs.renderer = data_table::CellRenderer::Badge;
cs.badges = {
{ "ok", "#22c55e", "" },
{ "error", "#ef4444", "ERR" },
{ "running", "#f59e0b", "RUN" },
{ "pending", "#a3a3a3", "..." },
};
}
// Aplica specs para panel LEFT — siempre v2.1 full
static void apply_full_specs(data_table::TableInput& t) {
t.column_specs.resize(k_cols);
for (int i = 0; i < k_cols; i++) t.column_specs[i].id = k_headers[i];
// col 0: id — Text (default)
// col 1: name — Text (default)
// col 2: status — CategoricalChip
apply_status_chip(t.column_specs[2]);
// col 3: duration_ms — Duration renderer
{
auto& cs = t.column_specs[3];
cs.renderer = data_table::CellRenderer::Duration;
cs.duration_warn_ms = 1000.0f;
cs.duration_error_ms = 5000.0f;
}
// col 4: priority — ColorScale
{
auto& cs = t.column_specs[4];
cs.renderer = data_table::CellRenderer::ColorScale;
cs.range_min = 0.0;
cs.range_max = 4.0;
cs.range_alpha = 0.30f;
// stops: low (green) → medium (amber) → high/critical (red)
cs.range_stops = {
{ 0.0f, "#22c55e" },
{ 0.5f, "#f59e0b" },
{ 1.0f, "#ef4444" },
};
}
}
// Aplica specs para panel RIGHT — degradado según versión seleccionada
static void apply_downgraded_specs(data_table::TableInput& t, SimVersion ver) {
t.column_specs.resize(k_cols);
for (int i = 0; i < k_cols; i++) t.column_specs[i].id = k_headers[i];
switch (ver) {
case SimVersion::V21:
// Igual que full (no debería llegar aquí, pero por completitud)
apply_full_specs(t);
break;
case SimVersion::V20:
// v2.0.0: full renderers disponibles, mismo resultado visual.
// La diferencia real es interna (split refactor en el módulo).
// Simulamos: idéntico a v2.1.
apply_status_chip(t.column_specs[2]);
{
auto& cs = t.column_specs[3];
cs.renderer = data_table::CellRenderer::Duration;
cs.duration_warn_ms = 1000.0f;
cs.duration_error_ms = 5000.0f;
}
{
auto& cs = t.column_specs[4];
cs.renderer = data_table::CellRenderer::ColorScale;
cs.range_min = 0.0;
cs.range_max = 4.0;
cs.range_alpha = 0.30f;
cs.range_stops = {
{ 0.0f, "#22c55e" },
{ 0.5f, "#f59e0b" },
{ 1.0f, "#ef4444" },
};
}
break;
case SimVersion::V15:
// v1.5.0: CategoricalChip no disponible → fallback Badge en status.
// Duration + ColorScale sí disponibles.
apply_status_badge(t.column_specs[2]);
{
auto& cs = t.column_specs[3];
cs.renderer = data_table::CellRenderer::Duration;
cs.duration_warn_ms = 1000.0f;
cs.duration_error_ms = 5000.0f;
}
{
auto& cs = t.column_specs[4];
cs.renderer = data_table::CellRenderer::ColorScale;
cs.range_min = 0.0;
cs.range_max = 4.0;
cs.range_alpha = 0.30f;
cs.range_stops = {
{ 0.0f, "#22c55e" },
{ 0.5f, "#f59e0b" },
{ 1.0f, "#ef4444" },
};
}
break;
case SimVersion::V14:
// v1.4.0: ni CategoricalChip, ni ColorScale → Badge básico en status,
// Duration degradada (Badge de rango), priority Text plano.
apply_status_badge(t.column_specs[2]);
// Duration: sin renderer específico → solo Text
t.column_specs[3].renderer = data_table::CellRenderer::Text;
// priority: Text plano
t.column_specs[4].renderer = data_table::CellRenderer::Text;
break;
}
}
} // anon
// ---------------------------------------------------------------------------
// render_compat — entry point
// ---------------------------------------------------------------------------
void render_compat() {
// ---- Cabecera de controles ----
ImGui::TextDisabled("Active module: data_table v2.1.0");
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
ImGui::SetNextItemWidth(360.0f);
ImGui::Combo("Compare with version", &g_selected_version,
k_version_labels, IM_ARRAYSIZE(k_version_labels));
// Nota informativa sobre la simulación
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
ImGui::TextDisabled("(educational simulation — real compat requires module flag, TBD)");
ImGui::Spacing();
// Botón TBD
ImGui::BeginDisabled(true);
ImGui::Button("Take screenshots both");
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::TextDisabled("TBD: requires capture API integration");
ImGui::Separator();
// ---- Labels de columnas ----
float col_w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.4f, 0.9f, 0.4f, 1.0f));
ImGui::Text("v2.1.0 — full renderers (current)");
ImGui::PopStyleColor();
ImGui::SameLine(col_w + ImGui::GetStyle().ItemSpacing.x);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.9f, 0.75f, 0.3f, 1.0f));
ImGui::Text("%s", k_version_labels[g_selected_version]);
ImGui::PopStyleColor();
ImGui::Spacing();
// ---- Side-by-side layout ----
SimVersion sim_ver = static_cast<SimVersion>(g_selected_version);
float avail_h = ImGui::GetContentRegionAvail().y;
if (ImGui::BeginTable("##compat_layout", 2,
ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("##col_left", ImGuiTableColumnFlags_None, 1.0f);
ImGui::TableSetupColumn("##col_right", ImGuiTableColumnFlags_None, 1.0f);
ImGui::TableNextRow();
// ---------- Panel izquierdo: v2.1 full ----------
ImGui::TableSetColumnIndex(0);
if (ImGui::BeginChild("##compat_left", ImVec2(-1.0f, avail_h - 4.0f), false)) {
data_table::TableInput tbl_left = make_base_table("compat_left");
apply_full_specs(tbl_left);
g_left.last_events.clear();
data_table::render("##compat_left_tbl", { tbl_left }, g_left.dt,
&g_left.last_events, false);
qa::consume_events(g_left.last_events);
}
ImGui::EndChild();
// ---------- Panel derecho: versión degradada ----------
ImGui::TableSetColumnIndex(1);
if (ImGui::BeginChild("##compat_right", ImVec2(-1.0f, avail_h - 4.0f), false)) {
data_table::TableInput tbl_right = make_base_table("compat_right");
apply_downgraded_specs(tbl_right, sim_ver);
g_right.last_events.clear();
data_table::render("##compat_right_tbl", { tbl_right }, g_right.dt,
&g_right.last_events, false);
qa::consume_events(g_right.last_events);
}
ImGui::EndChild();
ImGui::EndTable();
}
}
} // namespace tables_qa::tabs