491161204e
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
4.1 KiB
Markdown
72 lines
4.1 KiB
Markdown
---
|
|
id: 0010
|
|
title: Nodo tabla — contenedor cuadrado con filas que son nodos del grafo
|
|
status: pending
|
|
priority: medium
|
|
created: 2026-04-30
|
|
depends_on: [0004, 0005, 0008]
|
|
---
|
|
|
|
## Objetivo
|
|
|
|
Un tipo especial de nodo, **Table**, que se renderiza en el viewport como
|
|
un rectangulo (no circulo) y agrupa visualmente N entidades del grafo. Cada
|
|
fila de la tabla = un nodo real del grafo (con su `type_ref`, sus fields,
|
|
sus tags). Las filas se pueden **extraer** (salen al canvas como nodos
|
|
sueltos) y **meter** (un nodo suelto entra como fila).
|
|
|
|
Distinto del issue 0004 (vista tabla global por tipo): ese es una **ventana
|
|
auxiliar** que tabula entidades existentes; este es un **nodo en el grafo**
|
|
que existe en `entities` y posee filas via relaciones.
|
|
|
|
## Modelo de datos
|
|
|
|
- El nodo tabla es una entidad normal con `type_ref = 'Table'` y metadata:
|
|
```json
|
|
{
|
|
"row_type": "Person", // tipo esperado de las filas (puede ser vacio = mixto)
|
|
"columns": ["name","age","email"], // subset de fields del row_type a mostrar como columnas
|
|
"expanded": true // estado de UI persistido
|
|
}
|
|
```
|
|
- La pertenencia se modela con relaciones:
|
|
- `name = "CONTAINS_ROW"`, `from_entity = <table_id>`, `to_entity = <row_entity_id>`, `order = N`.
|
|
- Una fila puede pertenecer a varias tablas (varias relaciones `CONTAINS_ROW` apuntando al mismo nodo). Confirmado en la conversacion.
|
|
- Las columnas pueden ser fijas (`row_type` definido → columnas = subset de los `fields` de ese tipo) o libres (definidas por el creador de la tabla en `columns`).
|
|
|
|
## Render en viewport
|
|
|
|
- Forma: `square` o `rounded_square` con tamano dependiente del numero de filas (clamp a min/max).
|
|
- Cuando esta **colapsada**: caja con titulo + contador (`Table · 23 filas`).
|
|
- Cuando esta **expandida**: caja crece y dibuja un grid interno (filas x columnas) con los valores principales. Las filas son arrastrables individualmente.
|
|
- Las relaciones `CONTAINS_ROW` no se dibujan como aristas normales (serian ruido visual). En su lugar, una fila extraida muestra una arista fina punteada hacia su tabla de origen.
|
|
- Aristas entrantes/salientes del nodo tabla se dibujan al borde del rectangulo, no al centro.
|
|
|
|
## Operaciones
|
|
|
|
- **Crear tabla**: en context menu del viewport, "New table here". Pide `row_type` opcional. Crea entidad `Table` y la posiciona donde el click.
|
|
- **Anadir fila** (tabla expandida o seleccionada): boton "+ row" que crea una entidad nueva con `type_ref = row_type` (si esta definido) y la engancha via `CONTAINS_ROW`.
|
|
- **Extraer fila**: borra la relacion `CONTAINS_ROW`. La fila queda como nodo libre, posicionada al lado de la tabla.
|
|
- **Extraer multiples**: shift+click en filas dentro de la tabla expandida, "Extract selected".
|
|
- **Meter fila**: drag de un nodo sobre el rectangulo de una tabla. Confirm dialog si su `type_ref` no coincide con `row_type` de la tabla.
|
|
- **Editar fila**: doble-click en fila → abre Inspector con esa entidad seleccionada.
|
|
|
|
## Cambios en codigo
|
|
|
|
- `entity_ops`:
|
|
- `bool table_create(db_path, name, row_type, columns_csv, char* out_id)`.
|
|
- `bool table_add_row(db_path, table_id, char* out_row_id)` (crea entidad + relacion CONTAINS_ROW).
|
|
- `bool table_extract_row(db_path, table_id, row_id)` (borra solo la relacion).
|
|
- `bool table_attach_row(db_path, table_id, row_id, int order)`.
|
|
- `bool table_list_rows(db_path, table_id, vector<string>* out_row_ids)`.
|
|
- Renderer del viewport (`graph_viewport.cpp` y/o `graph_renderer`): branch para `is_table_node` (detectado por `type_ref == "Table"`) que dibuja rectangulo + grid expandido y devuelve hit-testing por filas individuales.
|
|
- `graph_load_from_operations`: filtrar las aristas `CONTAINS_ROW` para que no entren en el layout fisico (no aplican fuerzas).
|
|
|
|
## Definicion de hecho
|
|
|
|
- Crear tabla, anadir filas, extraer y meter filas funciona round-trip via SQLite.
|
|
- Tabla colapsada y expandida se renderizan correctamente en el viewport.
|
|
- Doble-click en fila enfoca el Inspector con esa entidad.
|
|
- Una fila puede pertenecer a varias tablas sin duplicarse.
|
|
- Borrar la tabla pregunta: "borrar tabla y todas sus filas" o "extraer filas y borrar solo la tabla".
|