mirror of
https://github.com/foambubble/foam.git
synced 2026-01-08 05:34:09 -05:00
[Graph-] Selection Panel (#1556)
* [Graph-] Added toggles to disable zoom & refocus movement on note selection [Graph-] Added neighbour depth slider & refocus speed slider * Refactored & updated the action of the refocusSpeedSlider into refocusDurationSlider to better reflect the underlying mechanism. * Refactored the naming and action of the refocus & zoom checkboxes to avoid double negatives * Removed refocus/Speed/Duration slider * Added comment to graph.css detailing reasons for removal of custom style rules for UI controls * Reverted(removed) null check added in dataviz.ts to keep focus on feature being implemented
This commit is contained in:
@@ -139,6 +139,7 @@ async function createGraphPanel(
|
||||
type: 'didUpdateStyle',
|
||||
payload: styles,
|
||||
});
|
||||
|
||||
updateGraph(panel, foam);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dg .c {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.dg .property-name {
|
||||
width: 90%;
|
||||
}
|
||||
/*
|
||||
[INFO] Custom width rules for dat.GUI controls (10% for controls, 90% for labels) were intentionally removed.
|
||||
This change was made to better accommodate new sliders, and to use dat.GUI's default proportions, which allocate more space to controls. If you notice any display issues (especially with type filter checkboxes), please verify in both light and dark VS Code themes.
|
||||
*/
|
||||
|
||||
.vscode-light .dg.main.taller-than-window .close-button {
|
||||
border-top: 1px solid #ddd;
|
||||
|
||||
@@ -4,6 +4,18 @@ const initGUI = () => {
|
||||
const gui = new dat.gui.GUI();
|
||||
const nodeTypeFilterFolder = gui.addFolder('Filter by type');
|
||||
const nodeTypeFilterControllers = new Map();
|
||||
const selectionFolder = gui.addFolder('Selection');
|
||||
|
||||
selectionFolder
|
||||
.add(model.selection, 'neighborDepth', 1, 5)
|
||||
.step(1)
|
||||
.name('Neighbor Depth')
|
||||
.onFinishChange(() => {
|
||||
update(m => m);
|
||||
});
|
||||
|
||||
selectionFolder.add(model.selection, 'enableRefocus').name('Refocus Enable');
|
||||
selectionFolder.add(model.selection, 'enableZoom').name('Zoom Enable');
|
||||
|
||||
return {
|
||||
/**
|
||||
@@ -91,11 +103,39 @@ let model = {
|
||||
note: true,
|
||||
tag: true,
|
||||
},
|
||||
|
||||
selection: {
|
||||
neighborDepth: 1,
|
||||
enableRefocus: true,
|
||||
enableZoom: true,
|
||||
}
|
||||
};
|
||||
|
||||
const graph = ForceGraph();
|
||||
const gui = initGUI();
|
||||
|
||||
function getNeighbors(nodeId, depth) {
|
||||
let neighbors = new Set([nodeId]);
|
||||
for (let i = 0; i < depth; i++) {
|
||||
let newNeighbors = new Set();
|
||||
for (const neighborId of neighbors) {
|
||||
if (model.graph.nodeInfo[neighborId]) {
|
||||
for (const n of model.graph.nodeInfo[neighborId].neighbors) {
|
||||
newNeighbors.add(n);
|
||||
}
|
||||
} else {
|
||||
// Node is missing from nodeInfo (e.g., has been deleted). Skipping.
|
||||
// This may make debugging difficult if nodes are unexpectedly missing from highlights.
|
||||
console.debug(`getNeighbors: node '${neighborId}' not found in nodeInfo, skipping.`);
|
||||
}
|
||||
}
|
||||
for (const newNeighbor of newNeighbors) {
|
||||
neighbors.add(newNeighbor);
|
||||
}
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
function update(patch) {
|
||||
const startTime = performance.now();
|
||||
// Apply the patch function to the model..
|
||||
@@ -105,20 +145,20 @@ function update(patch) {
|
||||
// compute highlighted elements
|
||||
const focusNodes = new Set();
|
||||
const focusLinks = new Set();
|
||||
if (model.hoverNode) {
|
||||
focusNodes.add(model.hoverNode);
|
||||
const info = model.graph.nodeInfo[model.hoverNode];
|
||||
info.neighbors.forEach(neighborId => focusNodes.add(neighborId));
|
||||
info.links.forEach(link => focusLinks.add(link));
|
||||
}
|
||||
if (model.selectedNodes) {
|
||||
model.selectedNodes.forEach(nodeId => {
|
||||
focusNodes.add(nodeId);
|
||||
const info = model.graph.nodeInfo[nodeId];
|
||||
info.neighbors.forEach(neighborId => focusNodes.add(neighborId));
|
||||
info.links.forEach(link => focusLinks.add(link));
|
||||
});
|
||||
}
|
||||
|
||||
const nodesToProcess = new Set([...model.selectedNodes, model.hoverNode].filter(Boolean));
|
||||
|
||||
nodesToProcess.forEach(nodeId => {
|
||||
const neighbors = getNeighbors(nodeId, model.selection.neighborDepth);
|
||||
neighbors.forEach(neighbor => focusNodes.add(neighbor));
|
||||
});
|
||||
|
||||
model.graph.links.forEach(link => {
|
||||
if (focusNodes.has(getLinkNodeId(link.source)) && focusNodes.has(getLinkNodeId(link.target))) {
|
||||
focusLinks.add(link);
|
||||
}
|
||||
});
|
||||
|
||||
model.focusNodes = focusNodes;
|
||||
model.focusLinks = focusLinks;
|
||||
|
||||
@@ -569,7 +609,12 @@ try {
|
||||
const noteId = message.payload;
|
||||
const node = graph.graphData().nodes.find(node => node.id === noteId);
|
||||
if (node) {
|
||||
graph.centerAt(node.x, node.y, 300).zoom(3, 300);
|
||||
if (model.selection.enableRefocus) {
|
||||
graph.centerAt(node.x, node.y, 300);
|
||||
}
|
||||
if (model.selection.enableZoom) {
|
||||
graph.zoom(3, 300);
|
||||
}
|
||||
Actions.selectNode(noteId);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user