feat(main): wire Inspector — load on selection, Save/Discard, refresh caches
Issue 0008: - types.yaml: stash ParsedTypes en g_app.parsed_types tras parsear (lo consume el Inspector para resolver schemas por type_ref). - load_input: tras load, llama views_inspector_clear_draft + _refresh_caches. - switch_to_project: limpia draft y parsed_types antes de cargar nuevo. - render(): seleccion → load_draft (si single sel y no dirty), Save → entity_update + reload_graph + relocaliza node_idx por sql_id + re-load draft + reselecciona en viewport, Discard → re-load draft. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -153,6 +153,8 @@ static bool switch_to_project(const std::string& slug) {
|
||||
|
||||
// Aplica paths nuevos y abre BDs
|
||||
apply_project_paths(slug);
|
||||
ge::views_inspector_clear_draft(g_app);
|
||||
g_app.parsed_types = ge::ParsedTypes{};
|
||||
if (!ge::layout_store_open(g_layout_db_path.c_str())) {
|
||||
std::fprintf(stderr, "[graph_explorer] layout_store_open failed: %s\n",
|
||||
g_layout_db_path.c_str());
|
||||
@@ -200,6 +202,8 @@ static bool load_input() {
|
||||
" %zu relations, %zu icons\n",
|
||||
pt.entities.size(), with_schema, total_fields,
|
||||
pt.relations.size(), codepoints.size());
|
||||
// Stash en AppState para que el Inspector resuelva schemas (issue 0008).
|
||||
g_app.parsed_types = std::move(pt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +247,12 @@ static bool load_input() {
|
||||
ge::views_reset_visibility(g_app);
|
||||
ge::views_apply_visibility(g_app);
|
||||
|
||||
// Inspector: refresca caches (tags distintas, lista de tipos) y limpia
|
||||
// cualquier draft anterior. El draft se cargara cuando el usuario
|
||||
// seleccione un nodo en el render loop.
|
||||
ge::views_inspector_clear_draft(g_app);
|
||||
ge::views_inspector_refresh_caches(g_app);
|
||||
|
||||
// --layout inicial (si llego del CLI)
|
||||
int idx = layout_name_to_index(g_layout_initial);
|
||||
if (idx >= 0) {
|
||||
@@ -638,6 +648,68 @@ static void render() {
|
||||
g_app.want_change_type = false;
|
||||
}
|
||||
|
||||
// ---- Inspector (issue 0008): sync draft con seleccion + save/discard ----
|
||||
{
|
||||
const auto& sel = g_viewport.selection;
|
||||
if (sel.size() == 1) {
|
||||
int sidx = sel.front();
|
||||
if (sidx >= 0 && sidx < g_graph.node_count
|
||||
&& sidx != g_app.insp_node_idx
|
||||
&& !g_app.insp_dirty) {
|
||||
const char* sql_id = ge::entity_index_lookup(
|
||||
g_idx, g_graph.nodes[sidx].user_data);
|
||||
ge::views_inspector_load_draft(g_app, sidx, sql_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_app.want_inspector_save && !g_app.insp_entity_id.empty()) {
|
||||
ge::EntityRecord rec = ge::views_inspector_build_record(g_app);
|
||||
if (ge::entity_update(g_app.input_db_path.c_str(), rec)) {
|
||||
std::fprintf(stdout, "[graph_explorer] saved entity %s\n",
|
||||
rec.id.c_str());
|
||||
// Reload del grafo para que cambios de name/type/etc. se reflejen
|
||||
// en el viewport (label, color del tipo, etc.).
|
||||
graph::GraphLoadStats stats{};
|
||||
if (ge::reload_graph(g_input, &g_graph, &stats)) {
|
||||
ge::entity_index_build(g_input.uri, &g_idx);
|
||||
ge::views_reset_visibility(g_app);
|
||||
ge::views_apply_visibility(g_app);
|
||||
int restored = ge::layout_store_load(g_graph_hash, g_graph);
|
||||
(void)restored;
|
||||
g_atlas_bound = false;
|
||||
g_gpu_dirty = true;
|
||||
}
|
||||
ge::views_inspector_refresh_caches(g_app);
|
||||
// Re-cargar draft tras el reload (los node_idx pueden haber cambiado
|
||||
// por reordenamiento de la BD). Buscamos el nuevo idx por sql_id.
|
||||
int new_idx = -1;
|
||||
for (int i = 0; i < g_graph.node_count; ++i) {
|
||||
const char* sid = ge::entity_index_lookup(
|
||||
g_idx, g_graph.nodes[i].user_data);
|
||||
if (sid && rec.id == sid) { new_idx = i; break; }
|
||||
}
|
||||
if (new_idx >= 0) {
|
||||
ge::views_inspector_load_draft(g_app, new_idx, rec.id.c_str());
|
||||
graph_viewport_clear_selection(g_graph, g_viewport);
|
||||
graph_viewport_add_to_selection(g_graph, g_viewport, new_idx);
|
||||
} else {
|
||||
ge::views_inspector_clear_draft(g_app);
|
||||
}
|
||||
} else {
|
||||
std::fprintf(stderr, "[graph_explorer] entity_update failed for %s\n",
|
||||
rec.id.c_str());
|
||||
}
|
||||
g_app.want_inspector_save = false;
|
||||
}
|
||||
|
||||
if (g_app.want_inspector_discard && !g_app.insp_entity_id.empty()) {
|
||||
int idx = g_app.insp_node_idx;
|
||||
std::string id = g_app.insp_entity_id;
|
||||
ge::views_inspector_load_draft(g_app, idx, id.c_str());
|
||||
g_app.want_inspector_discard = false;
|
||||
}
|
||||
|
||||
// Reset layout: limpia NF_PINNED en todos los nodos. El layout activo se
|
||||
// reaplica via apply_layout_tick (la toolbar ya lo incrementa).
|
||||
if (g_app.want_unpin_all) {
|
||||
|
||||
Reference in New Issue
Block a user