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:
@@ -0,0 +1,70 @@
|
||||
---
|
||||
id: 0036e
|
||||
title: Row click en NodeGroups enfoca la entidad en el viewport (kind-aware)
|
||||
status: pending
|
||||
priority: medium
|
||||
created: 2026-05-04
|
||||
parent: 0036
|
||||
depends_on: [0036b]
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Click sobre una fila en la NodeGroups window centra/selecciona la
|
||||
entidad correspondiente en el viewport. Comportamiento ramificado por
|
||||
kind:
|
||||
|
||||
- **kind = Group**: la fila ES una entidad. Click -> pan/zoom de la
|
||||
camara hacia su posicion + select.
|
||||
- **kind = Table** (DuckDB): la fila NO es entidad necesariamente.
|
||||
Resolucion **opcion (c)**:
|
||||
- Si ya existe una entidad promovida para ese row_id: click =
|
||||
focus.
|
||||
- Si no: click = no-op visual + texto disabled abajo del row tipo
|
||||
"promote first to focus" como hint sutil. Sin auto-promote.
|
||||
|
||||
## Cambios
|
||||
|
||||
### Estado para focus
|
||||
|
||||
`AppState::want_focus_entity = true; AppState::focus_entity_id = id;`
|
||||
Render loop consume el flag, recentra la camara al nodo, marca
|
||||
`viewport.selected_node_idx = ...` y limpia el flag.
|
||||
|
||||
(Probablemente ya existe esta infra desde issue 0011 promote+open
|
||||
inspector — reusar `app.want_focus_entity` / `app.focus_entity_id`.)
|
||||
|
||||
### Lookup de entidad para fila DuckDB
|
||||
|
||||
Para kind=Table, dado un row_id, comprobar si existe entity con
|
||||
`SELECT id FROM entities WHERE source = '<table_id>' AND
|
||||
metadata LIKE '%"row_id": "<row_id>"%' LIMIT 1` (o el query exacto
|
||||
usado en 0011 para detectar promovidas).
|
||||
|
||||
Cache simple: por window, mantener un `unordered_set<string>
|
||||
promoted_row_ids` que se rellena en cada paginacion. Asi el render
|
||||
sabe sin query extra que filas tienen entidad lista para focus.
|
||||
|
||||
### Render
|
||||
|
||||
Hacer la fila completa clickable (Selectable o boton invisible
|
||||
sobre la fila). Hover indica accion clara.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Click en row de Group: el viewport recentra al nodo y lo
|
||||
selecciona.
|
||||
- Click en row Table promovida: focus como kind=Group.
|
||||
- Click en row Table no promovida: no-op + hint visible.
|
||||
- Tests:
|
||||
- `test_node_groups_row_click_sets_focus_entity_for_group`
|
||||
- `test_node_groups_row_click_noop_for_unpromoted_table_row`
|
||||
|
||||
## TBD
|
||||
|
||||
Branch `issue/0036e-row-click-focus`, merge `--no-ff` a master.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Multi-select (fase 2).
|
||||
- Hover preview (fase 2).
|
||||
@@ -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")) {
|
||||
|
||||
Reference in New Issue
Block a user