// tab_buttons — ejercita CellRenderer::Button con 3 action_ids distintos // (retry / cancel / inspect) y consume sus TableEvents. // Muestra contador local de clicks por accion + boton Reset. // Issue 0108 fase 2. #include "tabs.h" #include "qa_state.h" #include "data_table/data_table.h" #include "core/logger.h" #include namespace tables_qa::tabs { namespace { qa::TabState g_st; int g_retry_clicks = 0; int g_cancel_clicks = 0; int g_inspect_clicks = 0; void seed() { // 5 filas x 6 columnas: id, name, status, action_retry, action_cancel, action_inspect // Las columnas de boton llevan el label del boton en la celda (se usa como button_label si // button_label esta vacio; aqui lo dejamos vacio para que el renderer use button_action). // Usamos una cadena plausible para cada celda de boton. g_st.back = { // id name status retry cancel inspect "1", "job-alpha", "ok", "Retry", "Cancel", "Inspect", "2", "job-beta", "error", "Retry", "Cancel", "Inspect", "3", "job-gamma", "running","Retry", "Cancel", "Inspect", "4", "job-delta", "error", "Retry", "Cancel", "Inspect", "5", "job-epsilon", "ok", "Retry", "Cancel", "Inspect", }; qa::rebuild_ptrs(g_st); } } // anon void render_buttons() { // 1. Seed si vacio if (g_st.back.empty()) seed(); // 2. UI — contadores locales + boton Reset (encima del BeginChild) ImGui::Text("Local click counters:"); ImGui::SameLine(); ImGui::Text("Retry: %d", g_retry_clicks); ImGui::SameLine(); ImGui::Text(" Cancel: %d", g_cancel_clicks); ImGui::SameLine(); ImGui::Text(" Inspect: %d", g_inspect_clicks); ImGui::SameLine(); if (ImGui::SmallButton("Reset")) { g_retry_clicks = 0; g_cancel_clicks = 0; g_inspect_clicks = 0; } // 3. Construir TableInput con 6 columnas data_table::TableInput tbl; tbl.name = "buttons"; tbl.headers = {"id", "name", "status", "action_retry", "action_cancel", "action_inspect"}; tbl.types = { data_table::ColumnType::Int, data_table::ColumnType::String, data_table::ColumnType::String, data_table::ColumnType::String, data_table::ColumnType::String, data_table::ColumnType::String, }; tbl.cells = g_st.ptrs.data(); tbl.rows = 5; tbl.cols = 6; // column_specs declarativos tbl.column_specs.resize(tbl.cols); for (int i = 0; i < tbl.cols; i++) tbl.column_specs[i].id = tbl.headers[i]; // status: CategoricalChip (ok=verde, error=rojo, running=amarillo) { auto& cs = tbl.column_specs[2]; cs.renderer = data_table::CellRenderer::CategoricalChip; cs.chips = { {"ok", "#22c55e"}, {"error", "#ef4444"}, {"running", "#f59e0b"}, }; } // action_retry { auto& cs = tbl.column_specs[3]; cs.renderer = data_table::CellRenderer::Button; cs.button_action = "retry"; cs.button_color_hex = "#3b82f6"; } // action_cancel { auto& cs = tbl.column_specs[4]; cs.renderer = data_table::CellRenderer::Button; cs.button_action = "cancel"; cs.button_color_hex = "#ef4444"; } // action_inspect { auto& cs = tbl.column_specs[5]; cs.renderer = data_table::CellRenderer::Button; cs.button_action = "inspect"; cs.button_color_hex = "#a855f7"; } // 4. Render dentro de BeginChild ImGui::BeginChild("##buttons_host", ImVec2(-1, -1)); g_st.last_events.clear(); data_table::render("##buttons_tbl", {tbl}, g_st.dt, &g_st.last_events, qa::toggles().show_chrome); ImGui::EndChild(); // 5. Consumir eventos globales (incrementa qa::counters) qa::consume_events(g_st.last_events); // 6. Iterar last_events para contadores locales + log de eventos de fila for (const auto& ev : g_st.last_events) { switch (ev.kind) { case data_table::TableEventKind::ButtonClick: if (ev.action_id == "retry") g_retry_clicks++; else if (ev.action_id == "cancel") g_cancel_clicks++; else if (ev.action_id == "inspect") g_inspect_clicks++; break; case data_table::TableEventKind::RowDoubleClick: fn_log::log_info("buttons: RowDoubleClick row=%d", ev.row); break; case data_table::TableEventKind::RowRightClick: fn_log::log_info("buttons: RowRightClick row=%d", ev.row); break; default: break; } } } } // namespace tables_qa::tabs