merge data_table migration (issue 0081-J)
Migrates registry_dashboard tables to data_table::render() via fn_table_viz.
This commit is contained in:
@@ -53,6 +53,11 @@ target_include_directories(registry_dashboard PRIVATE
|
||||
|
||||
target_link_libraries(registry_dashboard PRIVATE SQLite::SQLite3)
|
||||
|
||||
# Issue 0081-J: data_table::render via fn_table_viz static lib
|
||||
if(TARGET fn_table_viz)
|
||||
target_link_libraries(registry_dashboard PRIVATE fn_table_viz)
|
||||
endif()
|
||||
|
||||
# Sockets: ws2_32 on Windows, nothing extra on Linux
|
||||
if(WIN32)
|
||||
target_link_libraries(registry_dashboard PRIVATE ws2_32)
|
||||
|
||||
@@ -11,6 +11,18 @@ uses_functions:
|
||||
- pie_chart_cpp_viz
|
||||
- table_view_cpp_viz
|
||||
- sparkline_cpp_viz
|
||||
# data_table stack (issue 0081-J)
|
||||
- data_table_cpp_viz
|
||||
- viz_render_cpp_viz
|
||||
- compute_stage_cpp_core
|
||||
- compute_pipeline_cpp_core
|
||||
- tql_emit_cpp_core
|
||||
- tql_apply_cpp_core
|
||||
- tql_to_sql_cpp_core
|
||||
- lua_engine_cpp_core
|
||||
- join_tables_cpp_core
|
||||
- auto_detect_type_cpp_core
|
||||
- compute_column_stats_cpp_core
|
||||
# core (dashboard primitives)
|
||||
- dashboard_panel_cpp_core
|
||||
- dashboard_grid_cpp_core
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "viz/pie_chart.h"
|
||||
#include "viz/table_view.h"
|
||||
#include "viz/sparkline.h"
|
||||
#include "viz/data_table.h"
|
||||
#include "core/data_table_types.h"
|
||||
#include "core/icons_tabler.h"
|
||||
#include "core/dashboard_panel.h"
|
||||
#include "core/dashboard_grid.h"
|
||||
@@ -103,6 +105,191 @@ static std::string format_ts_relative(long long ts) {
|
||||
}
|
||||
static fn_ui::ProcessRunner g_add_runner;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// data_table::State — persistent per panel (issue 0081-J)
|
||||
// ---------------------------------------------------------------------------
|
||||
// One State per data-table panel. Must NOT be stack-local (see data_table.md
|
||||
// Gotchas: "State no stack-local").
|
||||
static data_table::State g_dt_recent_funcs;
|
||||
static data_table::State g_dt_apps;
|
||||
static data_table::State g_dt_analysis;
|
||||
static data_table::State g_dt_types;
|
||||
static data_table::State g_dt_vaults;
|
||||
static data_table::State g_dt_top_fn;
|
||||
static data_table::State g_dt_violations;
|
||||
static data_table::State g_dt_copies;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers: build a data_table::TableInput from registry row vectors
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Build a flat cells vector (row-major) + keep string backing alive.
|
||||
// Returns backing storage; `ti` is populated in-place.
|
||||
static std::vector<std::string> make_cells_recent_funcs(
|
||||
const std::vector<FunctionRow>& funcs,
|
||||
data_table::TableInput& ti)
|
||||
{
|
||||
ti.name = "functions";
|
||||
ti.headers = {"Name", "Lang", "Domain", "Kind", "Purity", "Tested", "Created"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::Date,
|
||||
};
|
||||
ti.rows = static_cast<int>(funcs.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(funcs.size() * ti.cols);
|
||||
for (const auto& f : funcs) {
|
||||
backing.push_back(f.name);
|
||||
backing.push_back(f.lang);
|
||||
backing.push_back(f.domain);
|
||||
backing.push_back(f.kind);
|
||||
backing.push_back(f.purity);
|
||||
backing.push_back(f.tested ? "yes" : "no");
|
||||
backing.push_back(f.created_at.substr(0, 10));
|
||||
}
|
||||
return backing;
|
||||
}
|
||||
|
||||
static std::vector<std::string> make_cells_apps(
|
||||
const std::vector<AppRow>& apps,
|
||||
data_table::TableInput& ti)
|
||||
{
|
||||
ti.name = "apps";
|
||||
ti.headers = {"Name", "Lang", "Domain", "Framework", "Git", "Description"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
};
|
||||
ti.rows = static_cast<int>(apps.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(apps.size() * ti.cols);
|
||||
for (const auto& a : apps) {
|
||||
std::string git_status;
|
||||
if (!a.repo_url.empty()) {
|
||||
git_status = "remote";
|
||||
} else if (!a.dir_path.empty()) {
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(
|
||||
std::filesystem::path(a.dir_path) / ".git", ec))
|
||||
git_status = "local";
|
||||
else
|
||||
git_status = "-";
|
||||
} else {
|
||||
git_status = "-";
|
||||
}
|
||||
backing.push_back(a.name);
|
||||
backing.push_back(a.lang);
|
||||
backing.push_back(a.domain);
|
||||
backing.push_back(a.framework);
|
||||
backing.push_back(git_status);
|
||||
backing.push_back(a.description);
|
||||
}
|
||||
return backing;
|
||||
}
|
||||
|
||||
static std::vector<std::string> make_cells_analysis(
|
||||
const std::vector<AnalysisRow>& analyses,
|
||||
data_table::TableInput& ti)
|
||||
{
|
||||
ti.name = "analysis";
|
||||
ti.headers = {"Name", "Lang", "Domain", "Description"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
};
|
||||
ti.rows = static_cast<int>(analyses.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(analyses.size() * ti.cols);
|
||||
for (const auto& a : analyses) {
|
||||
backing.push_back(a.name);
|
||||
backing.push_back(a.lang);
|
||||
backing.push_back(a.domain);
|
||||
backing.push_back(a.description);
|
||||
}
|
||||
return backing;
|
||||
}
|
||||
|
||||
static std::vector<std::string> make_cells_types(
|
||||
const std::vector<TypeRow>& types,
|
||||
data_table::TableInput& ti)
|
||||
{
|
||||
ti.name = "types";
|
||||
ti.headers = {"Name", "Lang", "Domain", "Algebraic", "Description"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
};
|
||||
ti.rows = static_cast<int>(types.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(types.size() * ti.cols);
|
||||
for (const auto& t : types) {
|
||||
backing.push_back(t.name);
|
||||
backing.push_back(t.lang);
|
||||
backing.push_back(t.domain);
|
||||
backing.push_back(t.algebraic);
|
||||
backing.push_back(t.description);
|
||||
}
|
||||
return backing;
|
||||
}
|
||||
|
||||
static std::vector<std::string> make_cells_vaults(
|
||||
const std::vector<VaultRow>& vaults,
|
||||
data_table::TableInput& ti)
|
||||
{
|
||||
ti.name = "vaults";
|
||||
ti.headers = {"Name", "Path", "Symlink", "Description"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
};
|
||||
ti.rows = static_cast<int>(vaults.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(vaults.size() * ti.cols);
|
||||
for (const auto& v : vaults) {
|
||||
backing.push_back(v.name);
|
||||
backing.push_back(v.path);
|
||||
backing.push_back(v.symlink ? "yes" : "no");
|
||||
backing.push_back(v.description);
|
||||
}
|
||||
return backing;
|
||||
}
|
||||
|
||||
// Converts backing vector to flat const char* array for TableInput.cells.
|
||||
// `ptrs` must outlive the render() call.
|
||||
static void cells_to_ptrs(const std::vector<std::string>& backing,
|
||||
std::vector<const char*>& ptrs)
|
||||
{
|
||||
ptrs.resize(backing.size());
|
||||
for (size_t i = 0; i < backing.size(); i++)
|
||||
ptrs[i] = backing[i].c_str();
|
||||
}
|
||||
|
||||
// Add modal state
|
||||
enum class AddKind : int { App = 0, Analysis = 1, Vault = 2 };
|
||||
static bool g_show_add = false;
|
||||
@@ -275,21 +462,15 @@ void draw_recent_functions(const std::vector<FunctionRow>& funcs) {
|
||||
"Run 'fn index' to populate the registry");
|
||||
return;
|
||||
}
|
||||
const char* headers[] = {"Name", "Lang", "Domain", "Kind", "Purity", "Tested", "Created"};
|
||||
constexpr int cols = 7;
|
||||
std::vector<std::string> cell_strings;
|
||||
cell_strings.reserve(funcs.size() * cols);
|
||||
for (auto& f : funcs) {
|
||||
cell_strings.push_back(f.name);
|
||||
cell_strings.push_back(f.lang);
|
||||
cell_strings.push_back(f.domain);
|
||||
cell_strings.push_back(f.kind);
|
||||
cell_strings.push_back(f.purity);
|
||||
cell_strings.push_back(f.tested ? "yes" : "no");
|
||||
cell_strings.push_back(f.created_at.substr(0, 10));
|
||||
}
|
||||
auto cells = to_cstr(cell_strings);
|
||||
table_view("##recent", headers, cols, cells.data(), static_cast<int>(funcs.size()));
|
||||
data_table::TableInput ti;
|
||||
auto backing = make_cells_recent_funcs(funcs, ti);
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##recent_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_recent_funcs", {ti}, g_dt_recent_funcs);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void draw_apps_list(const std::vector<AppRow>& apps) {
|
||||
@@ -298,37 +479,15 @@ void draw_apps_list(const std::vector<AppRow>& apps) {
|
||||
"Use the + Add button above or run 'fn sync'");
|
||||
return;
|
||||
}
|
||||
const char* headers[] = {"Name", "Lang", "Domain", "Framework", "Git", "Description"};
|
||||
constexpr int cols = 6;
|
||||
std::vector<std::string> cell_strings;
|
||||
cell_strings.reserve(apps.size() * cols);
|
||||
for (auto& a : apps) {
|
||||
cell_strings.push_back(a.name);
|
||||
cell_strings.push_back(a.lang);
|
||||
cell_strings.push_back(a.domain);
|
||||
cell_strings.push_back(a.framework);
|
||||
// Indicador de git: tiene repo remoto (gitea), solo local, o ninguno.
|
||||
// - "remote": repo_url poblado en el frontmatter del app.md
|
||||
// - "local": hay .git/ en dir_path pero sin repo_url
|
||||
// - "-": ni .git ni repo_url
|
||||
std::string git_status;
|
||||
if (!a.repo_url.empty()) {
|
||||
git_status = "remote";
|
||||
} else if (!a.dir_path.empty()) {
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(std::filesystem::path(a.dir_path) / ".git", ec)) {
|
||||
git_status = "local";
|
||||
} else {
|
||||
git_status = "-";
|
||||
}
|
||||
} else {
|
||||
git_status = "-";
|
||||
}
|
||||
cell_strings.push_back(git_status);
|
||||
cell_strings.push_back(a.description);
|
||||
}
|
||||
auto cells = to_cstr(cell_strings);
|
||||
table_view("##apps", headers, cols, cells.data(), static_cast<int>(apps.size()));
|
||||
data_table::TableInput ti;
|
||||
auto backing = make_cells_apps(apps, ti);
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##apps_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_apps", {ti}, g_dt_apps);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void draw_analysis_list(const std::vector<AnalysisRow>& analyses) {
|
||||
@@ -337,18 +496,15 @@ void draw_analysis_list(const std::vector<AnalysisRow>& analyses) {
|
||||
"Use the + Add button above with kind = Analysis");
|
||||
return;
|
||||
}
|
||||
const char* headers[] = {"Name", "Lang", "Domain", "Description"};
|
||||
constexpr int cols = 4;
|
||||
std::vector<std::string> cell_strings;
|
||||
cell_strings.reserve(analyses.size() * cols);
|
||||
for (auto& a : analyses) {
|
||||
cell_strings.push_back(a.name);
|
||||
cell_strings.push_back(a.lang);
|
||||
cell_strings.push_back(a.domain);
|
||||
cell_strings.push_back(a.description);
|
||||
}
|
||||
auto cells = to_cstr(cell_strings);
|
||||
table_view("##analysis", headers, cols, cells.data(), static_cast<int>(analyses.size()));
|
||||
data_table::TableInput ti;
|
||||
auto backing = make_cells_analysis(analyses, ti);
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##analysis_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_analysis", {ti}, g_dt_analysis);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void draw_types_list(const std::vector<TypeRow>& types) {
|
||||
@@ -357,19 +513,15 @@ void draw_types_list(const std::vector<TypeRow>& types) {
|
||||
"Types are indexed from the registry alongside functions");
|
||||
return;
|
||||
}
|
||||
const char* headers[] = {"Name", "Lang", "Domain", "Algebraic", "Description"};
|
||||
constexpr int cols = 5;
|
||||
std::vector<std::string> cell_strings;
|
||||
cell_strings.reserve(types.size() * cols);
|
||||
for (auto& t : types) {
|
||||
cell_strings.push_back(t.name);
|
||||
cell_strings.push_back(t.lang);
|
||||
cell_strings.push_back(t.domain);
|
||||
cell_strings.push_back(t.algebraic);
|
||||
cell_strings.push_back(t.description);
|
||||
}
|
||||
auto cells = to_cstr(cell_strings);
|
||||
table_view("##types", headers, cols, cells.data(), static_cast<int>(types.size()));
|
||||
data_table::TableInput ti;
|
||||
auto backing = make_cells_types(types, ti);
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##types_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_types", {ti}, g_dt_types);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -686,27 +838,44 @@ void draw_monitor(RegistryData& data) {
|
||||
if (cu.top_functions.empty()) {
|
||||
ImGui::TextDisabled("No function calls recorded yet. Hook fires on next session.");
|
||||
} else {
|
||||
const ImGuiTableFlags tf = ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders
|
||||
| ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY;
|
||||
if (ImGui::BeginTable("##monitor_top_fn", 6, tf, ImVec2(0, 0))) {
|
||||
ImGui::TableSetupColumn("Function ID");
|
||||
ImGui::TableSetupColumn("Calls");
|
||||
ImGui::TableSetupColumn("7d");
|
||||
ImGui::TableSetupColumn("Errors");
|
||||
ImGui::TableSetupColumn("Error %");
|
||||
ImGui::TableSetupColumn("Mean ms");
|
||||
ImGui::TableHeadersRow();
|
||||
// Build TableInput for data_table::render
|
||||
data_table::TableInput ti;
|
||||
ti.name = "top_functions";
|
||||
ti.headers = {"Function ID", "Calls", "7d", "Errors", "Error %", "Mean ms"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::Int,
|
||||
data_table::ColumnType::Int,
|
||||
data_table::ColumnType::Int,
|
||||
data_table::ColumnType::Float,
|
||||
data_table::ColumnType::Float,
|
||||
};
|
||||
ti.rows = static_cast<int>(cu.top_functions.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(cu.top_functions.size() * 6);
|
||||
char buf[32];
|
||||
for (const auto& r : cu.top_functions) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(r.function_id.c_str());
|
||||
ImGui::TableSetColumnIndex(1); ImGui::Text("%d", r.calls_total);
|
||||
ImGui::TableSetColumnIndex(2); ImGui::Text("%d", r.calls_7d);
|
||||
ImGui::TableSetColumnIndex(3); ImGui::Text("%d", r.errors_total);
|
||||
ImGui::TableSetColumnIndex(4); ImGui::Text("%.1f%%", r.error_rate * 100.0);
|
||||
ImGui::TableSetColumnIndex(5); ImGui::Text("%.0f", r.mean_duration_ms);
|
||||
}
|
||||
ImGui::EndTable();
|
||||
backing.push_back(r.function_id);
|
||||
std::snprintf(buf, sizeof(buf), "%d", r.calls_total);
|
||||
backing.push_back(buf);
|
||||
std::snprintf(buf, sizeof(buf), "%d", r.calls_7d);
|
||||
backing.push_back(buf);
|
||||
std::snprintf(buf, sizeof(buf), "%d", r.errors_total);
|
||||
backing.push_back(buf);
|
||||
std::snprintf(buf, sizeof(buf), "%.1f%%", r.error_rate * 100.0);
|
||||
backing.push_back(buf);
|
||||
std::snprintf(buf, sizeof(buf), "%.0f", r.mean_duration_ms);
|
||||
backing.push_back(buf);
|
||||
}
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##top_fn_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_top_fn", {ti}, g_dt_top_fn);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -714,25 +883,35 @@ void draw_monitor(RegistryData& data) {
|
||||
if (cu.recent_violations.empty()) {
|
||||
ImGui::TextDisabled("No antipattern violations detected.");
|
||||
} else {
|
||||
const ImGuiTableFlags tf = ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders
|
||||
| ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY;
|
||||
if (ImGui::BeginTable("##monitor_viol", 5, tf, ImVec2(0, 0))) {
|
||||
ImGui::TableSetupColumn("When");
|
||||
ImGui::TableSetupColumn("Rule");
|
||||
ImGui::TableSetupColumn("Severity");
|
||||
ImGui::TableSetupColumn("Function");
|
||||
ImGui::TableSetupColumn("Snippet");
|
||||
ImGui::TableHeadersRow();
|
||||
data_table::TableInput ti;
|
||||
ti.name = "violations";
|
||||
ti.headers = {"When", "Rule", "Severity", "Function", "Snippet"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
};
|
||||
ti.rows = static_cast<int>(cu.recent_violations.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(cu.recent_violations.size() * 5);
|
||||
for (const auto& r : cu.recent_violations) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(format_ts(r.ts).c_str());
|
||||
ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(r.rule_id.c_str());
|
||||
ImGui::TableSetColumnIndex(2); ImGui::TextUnformatted(r.severity.c_str());
|
||||
ImGui::TableSetColumnIndex(3); ImGui::TextUnformatted(r.function_id.c_str());
|
||||
ImGui::TableSetColumnIndex(4); ImGui::TextUnformatted(r.command_snippet.c_str());
|
||||
}
|
||||
ImGui::EndTable();
|
||||
backing.push_back(format_ts(r.ts));
|
||||
backing.push_back(r.rule_id);
|
||||
backing.push_back(r.severity);
|
||||
backing.push_back(r.function_id);
|
||||
backing.push_back(r.command_snippet);
|
||||
}
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##viol_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_violations", {ti}, g_dt_violations);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -793,25 +972,37 @@ void draw_monitor(RegistryData& data) {
|
||||
if (cu.copies.empty()) {
|
||||
ImGui::TextDisabled("No copied code detected. Run `fn doctor copied-code` or `call_monitor copied-code`.");
|
||||
} else {
|
||||
const ImGuiTableFlags tf = ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders
|
||||
| ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY;
|
||||
if (ImGui::BeginTable("##monitor_copies", 5, tf, ImVec2(0, 0))) {
|
||||
ImGui::TableSetupColumn("Kind");
|
||||
ImGui::TableSetupColumn("Sim");
|
||||
ImGui::TableSetupColumn("App File");
|
||||
ImGui::TableSetupColumn("App Function");
|
||||
ImGui::TableSetupColumn("Registry ID");
|
||||
ImGui::TableHeadersRow();
|
||||
data_table::TableInput ti;
|
||||
ti.name = "copies";
|
||||
ti.headers = {"Kind", "Sim", "App File", "App Function", "Registry ID"};
|
||||
ti.types = {
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::Float,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
data_table::ColumnType::String,
|
||||
};
|
||||
ti.rows = static_cast<int>(cu.copies.size());
|
||||
ti.cols = static_cast<int>(ti.headers.size());
|
||||
|
||||
std::vector<std::string> backing;
|
||||
backing.reserve(cu.copies.size() * 5);
|
||||
char buf[32];
|
||||
for (const auto& r : cu.copies) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(r.kind.c_str());
|
||||
ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", r.similarity);
|
||||
ImGui::TableSetColumnIndex(2); ImGui::TextUnformatted(r.app_file.c_str());
|
||||
ImGui::TableSetColumnIndex(3); ImGui::TextUnformatted(r.app_function.c_str());
|
||||
ImGui::TableSetColumnIndex(4); ImGui::TextUnformatted(r.registry_id.c_str());
|
||||
}
|
||||
ImGui::EndTable();
|
||||
backing.push_back(r.kind);
|
||||
std::snprintf(buf, sizeof(buf), "%.2f", r.similarity);
|
||||
backing.push_back(buf);
|
||||
backing.push_back(r.app_file);
|
||||
backing.push_back(r.app_function);
|
||||
backing.push_back(r.registry_id);
|
||||
}
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
|
||||
ImGui::BeginChild("##copies_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_copies", {ti}, g_dt_copies);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -916,18 +1107,14 @@ void draw_projects_list(RegistryData& data) {
|
||||
empty_state("( no data )", "No vaults in this project",
|
||||
"Use the + Add button with kind = Vault (requires a project)");
|
||||
} else {
|
||||
const char* headers[] = {"Name", "Path", "Symlink", "Description"};
|
||||
std::vector<std::string> cells;
|
||||
cells.reserve(d.vaults.size() * 4);
|
||||
for (auto& v : d.vaults) {
|
||||
cells.push_back(v.name);
|
||||
cells.push_back(v.path);
|
||||
cells.push_back(v.symlink ? "yes" : "no");
|
||||
cells.push_back(v.description);
|
||||
}
|
||||
auto cp = to_cstr(cells);
|
||||
table_view("##vaults", headers, 4, cp.data(),
|
||||
static_cast<int>(d.vaults.size()));
|
||||
data_table::TableInput ti;
|
||||
auto backing = make_cells_vaults(d.vaults, ti);
|
||||
std::vector<const char*> ptrs;
|
||||
cells_to_ptrs(backing, ptrs);
|
||||
ti.cells = ptrs.data();
|
||||
ImGui::BeginChild("##vaults_dt_wrap", ImVec2(-1, -1));
|
||||
data_table::render("##dt_vaults", {ti}, g_dt_vaults);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user