feat(0036e): row click en NodeGroups enfoca la entidad (kind-aware)

- Reusa la infra de focus existente (AppState::want_focus_entity /
  focus_entity_id) ya cableada en main.cpp desde 0011.
- kind=Group: single click sobre la fila pone want_focus_entity con
  row.id; tooltip "Click to focus entity in viewport" en hover.
  El doble click sigue funcionando (mismo efecto). El menu contextual
  y el boton Promote-out-of-group quedan intactos.
- kind=Table promovida (row.promoted_entity_id no vacio): single click
  pone want_focus_entity con promoted_entity_id; tooltip de focus.
- kind=Table no promovida: single click es no-op visual; tooltip
  "promote first to focus\n(double click or right click to promote)"
  como hint sutil. El doble click sigue lanzando el flujo de promote
  (legado de 0036c) y el menu contextual ofrece Promote.
- Sin cambios en el handler de main.cpp — la logica de pan/zoom + select
  + load inspector ya existe y se reutiliza tal cual.
- Sin tests Python nuevos: el comportamiento es UI ImGui (no testeable
  desde pytest). 102 passed WSL / 91+11 skipped Windows sin regresion.

Refs: issues/0036e-row-click-focus-viewport.md
This commit is contained in:
2026-05-04 01:06:30 +02:00
parent 8bfe0b841c
commit f4e4dd5a0b
2 changed files with 99 additions and 6 deletions
+29 -6
View File
@@ -2089,14 +2089,18 @@ void views_node_groups_window(AppState& app) {
ImGui::Selectable(row.id.c_str(), false, sf);
if (is_group) {
// En kind=Group la fila YA es una entidad real del grafo.
// Doble click → focus inspector. Right click → focus.
// (El boton "Promote" no aplica — 0036d hace eso para
// contextos donde tenga sentido.)
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
// 0036e: en kind=Group la fila YA es una entidad real del
// grafo. Single click → focus + select en viewport.
// Doble click tambien dispara focus (mismo efecto).
// Right click → menu contextual con focus.
if (ImGui::IsItemHovered()
&& (ImGui::IsMouseClicked(0) || ImGui::IsMouseDoubleClicked(0))) {
app.want_focus_entity = true;
app.focus_entity_id = row.id;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Click to focus entity in viewport");
}
if (ImGui::BeginPopupContextItem()) {
if (ImGui::MenuItem(TI_FOCUS " Focus in Inspector")) {
app.want_focus_entity = true;
@@ -2122,8 +2126,20 @@ void views_node_groups_window(AppState& app) {
ImGui::SetTooltip("Promote out of group (move to canvas)");
}
} else {
// kind=Table — comportamiento original (DuckDB-backed).
// kind=Table (DuckDB-backed).
// 0036e: click ramificado por estado de promocion:
// - promovida → single click = focus en viewport.
// - no promovida → single click = no-op + hint tooltip.
// El doble click sobre fila no promovida sigue lanzando
// el flujo de promote (legado de 0036c) por convenience.
bool is_promoted = !row.promoted_entity_id.empty();
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) {
if (is_promoted) {
app.want_focus_entity = true;
app.focus_entity_id = row.promoted_entity_id;
}
// else: no-op (hint mostrado via tooltip abajo).
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
if (is_promoted) {
app.want_focus_entity = true;
@@ -2134,6 +2150,13 @@ void views_node_groups_window(AppState& app) {
app.promote_row_id = row.id;
}
}
if (ImGui::IsItemHovered()) {
if (is_promoted) {
ImGui::SetTooltip("Click to focus entity in viewport");
} else {
ImGui::SetTooltip("promote first to focus\n(double click or right click to promote)");
}
}
if (ImGui::BeginPopupContextItem()) {
if (is_promoted) {
if (ImGui::MenuItem(TI_FOCUS " Focus in Inspector")) {