fix: docking gaps + hover radius + node spread + markdown notes
Bug fixes - ImGui ID conflict en menu Change type: dedup tipos del grafo + defaults; PushID/PopID por entrada. - Dockspace ya no tapa la toolbar: se posiciona 44 px por debajo, asi las ventanas dockeadas al borde superior quedan bajo la barra de filtros, no detras. - Hover radius proporcional al tamaño visual del nodo: query espacial amplio (24/zoom) + filtro fino por (radio_visual + 2 px) / zoom. El tooltip solo se dispara si el raton esta efectivamente sobre el nodo. Layout - Default layout = grid (en vez de force) para que los grafos cargados se distribuyan ordenadamente al abrir. - Boton "Reset layout" en la toolbar: limpia NF_PINNED en todos los nodos, resetea velocidades y reaplica el layout activo. - Nodos recien creados (add_node, duplicate) caen en un anillo poisson alrededor del centro de la vista, no en el origen. Posicion determinista por user_data para que el mismo nodo no salte entre reloads. Notes (markdown) - Panel "Note" (dockeable) abierto con doble click sobre un nodo. - entity_get_notes / entity_set_notes en entity_ops sobre la columna `notes` de operations.db (ya existente en el schema). - Ctrl+S guarda. Cabecera muestra entity, type, id.
This commit is contained in:
@@ -286,6 +286,49 @@ bool relation_insert(const char* db_path, const char* from_id, const char* to_id
|
||||
return ok;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Notes (markdown)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool entity_get_notes(const char* db_path, const char* id, std::string* out) {
|
||||
if (!db_path || !id || !out) return false;
|
||||
out->clear();
|
||||
sqlite3* db = nullptr;
|
||||
if (sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) {
|
||||
if (db) sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
sqlite3_stmt* st = nullptr;
|
||||
if (sqlite3_prepare_v2(db, "SELECT notes FROM entities WHERE id = ?", -1, &st, nullptr) != SQLITE_OK) {
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
sqlite3_bind_text(st, 1, id, -1, SQLITE_TRANSIENT);
|
||||
bool ok = false;
|
||||
if (sqlite3_step(st) == SQLITE_ROW) {
|
||||
const unsigned char* p = sqlite3_column_text(st, 0);
|
||||
if (p) *out = (const char*)p;
|
||||
ok = true;
|
||||
}
|
||||
sqlite3_finalize(st);
|
||||
sqlite3_close(db);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool entity_set_notes(const char* db_path, const char* id, const char* notes) {
|
||||
if (!db_path || !id) return false;
|
||||
sqlite3* db = nullptr;
|
||||
if (sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READWRITE, nullptr) != SQLITE_OK) {
|
||||
if (db) sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
std::string ts = now_iso();
|
||||
const char* p[3] = { notes ? notes : "", ts.c_str(), id };
|
||||
bool ok = exec_one(db, "UPDATE entities SET notes = ?, updated_at = ? WHERE id = ?", p, 3);
|
||||
sqlite3_close(db);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Index user_data -> sql id
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user