feat(0036c): doble click en Group abre NodeGroups; cleanup Table panel
Cambia el dispatch del doble click sobre nodos del viewport: si el tipo
es Group o Table, ahora abre/enfoca la NodeGroups window correspondiente
via views_node_groups_open(...). El branch de Group ya no carga el
panel Table generico con un filtro group_id (logica heredada de 0035d
que provocaba el bug de "tabla vacia").
Limpieza correlativa en views_table:
- Eliminado el breadcrumb "Group: <name> (N)" + boton Clear filter.
- Eliminado el filtro r.group_id != table_filter_group_id en
build_visible y la restriccion de types_present.
- Eliminado el reset on-close de los campos de filtro.
Eliminados los campos AppState::table_filter_group_id y
table_filter_group_name (audit: git grep table_filter_group_id devuelve
vacio fuera de issues/).
Render de NodeGroups ahora consume focus_request: llama
SetNextWindowFocus() antes de Begin y SetWindowFocus() dentro, asi la
window queda al frente tanto al crearse como al re-enfocarse.
El right-click "Open NodeGroups" del context menu sigue intacto
(want_toggle_nodegroups + node_groups_set_expanded). El doble click es
flujo paralelo nuevo.
Refs: issues/0036c-double-click-group-opens-nodegroups.md
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -1733,41 +1733,12 @@ void render_one_table(AppState& app, std::vector<int>& 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<std::string> types_present;
|
||||
types_present.reserve(8);
|
||||
{
|
||||
std::unordered_set<std::string> 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) {
|
||||
|
||||
@@ -239,12 +239,6 @@ struct AppState {
|
||||
std::unordered_map<int, std::string> 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: <name>
|
||||
// (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
|
||||
|
||||
Reference in New Issue
Block a user