diff --git a/main.cpp b/main.cpp index e4bb047..f4853fa 100644 --- a/main.cpp +++ b/main.cpp @@ -1941,32 +1941,32 @@ static void render() { } // Note editor — abrir / guardar. - // Excepcion (issue 0035d): si el nodo es un Group, en lugar de abrir - // Note se abre el panel Table con filtro por group_id. + // Excepcion (issue 0036c): si el nodo es un Group o un Table, abrir/enfocar + // la NodeGroups window correspondiente en lugar del panel Note. if (g_app.want_open_note && g_app.open_note_target >= 0 && g_app.open_note_target < g_graph.node_count) { int n = g_app.open_note_target; const char* sql_id = ge::entity_index_lookup(g_idx, g_graph.nodes[n].user_data); - // Detectar si el nodo es de tipo Group. + // Detectar si el nodo es de tipo Group o Table. bool is_group = false; + bool is_table = false; uint16_t tid = g_graph.nodes[n].type_id; const char* type_name = (tid < (uint16_t)g_graph.type_count && g_graph.types[tid].name) ? g_graph.types[tid].name : ""; if (type_name && std::strcmp(type_name, "Group") == 0) is_group = true; + else if (type_name && std::strcmp(type_name, "Table") == 0) is_table = true; - if (is_group && sql_id) { - // Drill-in: abrir Table panel filtrado por group_id = sql_id. - g_app.table_filter_group_id = sql_id; - const char* lbl = graph::graph_label(&g_graph, g_graph.nodes[n].label_idx); - g_app.table_filter_group_name = lbl ? lbl : sql_id; - // Reset filtros que pueden ocultar las filas del grupo. - g_app.table_search_buf[0] = 0; - g_app.table_col_filters.clear(); - g_app.table_show_all = true; - g_app.panel_table = true; - ImGui::SetWindowFocus("Table"); + if ((is_group || is_table) && sql_id) { + // Drill-in: abre/enfoca la NodeGroups window. views_node_groups_open + // crea la entry si no existe, marca focus_request=true en cualquier + // caso (el render lo consume con SetWindowFocus). + ge::NodeGroupsKind kind = is_group + ? ge::NodeGroupsKind::Group + : ge::NodeGroupsKind::Table; + ge::views_node_groups_open(g_app, sql_id, kind, + g_input_path.c_str()); } else if (sql_id) { std::string md; ge::entity_get_notes(g_app.input_db_path.c_str(), sql_id, &md); diff --git a/views.cpp b/views.cpp index 1823b44..97619b8 100644 --- a/views.cpp +++ b/views.cpp @@ -1733,41 +1733,12 @@ void render_one_table(AppState& app, std::vector& visible_indices) { } // namespace void views_table(AppState& app) { - // Si el panel se cierra, limpiamos el filtro de grupo (RAM-only). - if (!app.panel_table) { - if (!app.table_filter_group_id.empty()) { - app.table_filter_group_id.clear(); - app.table_filter_group_name.clear(); - } - return; - } + if (!app.panel_table) return; if (!ImGui::Begin("Table", &app.panel_table)) { ImGui::End(); return; } - // Breadcrumb de drill-in por grupo (issue 0035d). - if (!app.table_filter_group_id.empty()) { - // Contar filas que pertenecen a este grupo (sin aplicar otros filtros). - size_t n_group = 0; - for (const auto& r : app.table_rows) { - if (r.group_id == app.table_filter_group_id) ++n_group; - } - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.85f, 0.75f, 0.35f, 1.0f)); - ImGui::Text(TI_FOLDER " Group: %s (%zu)", - app.table_filter_group_name.empty() - ? app.table_filter_group_id.c_str() - : app.table_filter_group_name.c_str(), - n_group); - ImGui::PopStyleColor(); - ImGui::SameLine(); - if (fn_ui::button("Clear group filter", fn_ui::ButtonVariant::Subtle)) { - app.table_filter_group_id.clear(); - app.table_filter_group_name.clear(); - } - ImGui::Separator(); - } - // Toolbar superior: search + show all. ImGui::SetNextItemWidth(220); ImGui::InputTextWithHint("##tsearch", TI_SEARCH " filter name/id...", @@ -1806,15 +1777,12 @@ void views_table(AppState& app) { return; } - // Indices por tipo. Si hay filtro de grupo (issue 0035d) acotamos los - // types tabulables a los presentes dentro del grupo. + // Indices por tipo presentes en el snapshot. std::vector types_present; types_present.reserve(8); { std::unordered_set seen; for (const auto& r : app.table_rows) { - if (!app.table_filter_group_id.empty() - && r.group_id != app.table_filter_group_id) continue; if (seen.insert(r.type_ref).second) types_present.push_back(r.type_ref); } std::sort(types_present.begin(), types_present.end()); @@ -1825,10 +1793,6 @@ void views_table(AppState& app) { v.reserve(app.table_rows.size()); for (size_t i = 0; i < app.table_rows.size(); ++i) { const auto& r = app.table_rows[i]; - // Drill-in por grupo (issue 0035d): si hay filtro activo, solo - // pasan filas cuyo group_id coincide. - if (!app.table_filter_group_id.empty() - && r.group_id != app.table_filter_group_id) continue; if (type_filter && r.type_ref != type_filter) continue; if (app.table_search_buf[0] && !ci_contains(r.name, app.table_search_buf) @@ -2036,13 +2000,20 @@ void views_node_groups_window(AppState& app) { m.entity_id.c_str()); } ImGui::SetNextWindowSize(ImVec2(640, 460), ImGuiCond_FirstUseEver); - if (w.focus_request) { - // El render lo consume 0036c — por ahora simplemente lo limpiamos - // tras un frame para que no se quede pegado. Cuando 0036c llegue - // anadira ImGui::SetNextWindowFocus() aqui. + const bool focus_now = w.focus_request; + if (focus_now) { + // 0036c: forzar foco antes de Begin para que la window quede al + // frente al abrirse o reabrirse desde doble click. + ImGui::SetNextWindowFocus(); w.focus_request = false; } if (!ImGui::Begin(title, &w.open)) { ImGui::End(); continue; } + if (focus_now) { + // Doble seguridad: tambien lo llamamos dentro del Begin/End por + // si la window estaba ya abierta y ImGui ignora SetNextWindowFocus + // en ese caso (raro, pero barato). + ImGui::SetWindowFocus(); + } // Header de info (varia por kind) if (is_group) { diff --git a/views.h b/views.h index de87486..5c86eb4 100644 --- a/views.h +++ b/views.h @@ -239,12 +239,6 @@ struct AppState { std::unordered_map table_col_filters; char table_filter_input[96] = {}; // buffer del popup activo int table_filter_pending_col = -1; // col_user_id en edicion - // Drill-in por grupo (issue 0035d): cuando esta seteado, la tabla solo - // muestra filas cuyo `group_id` coincida. Header muestra "Group: - // (N)" + boton "Clear group filter". RAM-only — al cerrar el panel se - // limpia. - std::string table_filter_group_id; // "" = sin filtro - std::string table_filter_group_name; // label legible // ---- Type Editor (issue 0007) ------------------------------------------ // Draft del editor de tipos. Se inicializa con una copia de parsed_types