Index: tools/turbolizer/graph-view.js |
diff --git a/tools/turbolizer/graph-view.js b/tools/turbolizer/graph-view.js |
index aa1b638f57ba248de205754882c872ff48231405..efddc90a7d8b771f4134aa8ebf1fca8edf952d52 100644 |
--- a/tools/turbolizer/graph-view.js |
+++ b/tools/turbolizer/graph-view.js |
@@ -173,16 +173,30 @@ class GraphView extends View { |
if (d3.event.keyCode == 13) { |
graph.state.selection.clear(); |
var reg = new RegExp(this.value); |
+ var filterFunction = function(n) { |
+ return (reg.exec(n.getDisplayLabel()) != null || |
+ (graph.state.showTypes && reg.exec(n.getDisplayType())) || |
+ reg.exec(n.opcode) != null); |
+ }; |
+ if (d3.event.ctrlKey) { |
+ graph.nodes.forEach(function(n, i) { |
+ if (filterFunction(n)) { |
+ n.visible = true; |
+ } |
+ }); |
+ graph.updateGraphVisibility(); |
+ } |
var selected = graph.visibleNodes.each(function(n) { |
- if (reg.exec(n.getDisplayLabel()) != null || |
- (graph.state.showTypes && reg.exec(n.getDisplayType())) || |
- reg.exec(n.opcode) != null) { |
+ if (filterFunction(n)) { |
graph.state.selection.select(this, true); |
} |
}); |
+ graph.connectVisibleSelectedNodes(); |
+ graph.updateGraphVisibility(); |
this.blur(); |
graph.viewSelection(); |
} |
+ d3.event.stopPropagation(); |
}); |
// listen for key events |
@@ -243,9 +257,10 @@ class GraphView extends View { |
} |
initializeContent(data, rememberedSelection) { |
- this.createGraph(data); |
+ this.createGraph(data, rememberedSelection); |
if (rememberedSelection != null) { |
this.attachSelection(rememberedSelection); |
+ this.connectVisibleSelectedNodes(); |
} |
this.updateGraphVisibility(); |
} |
@@ -259,7 +274,7 @@ class GraphView extends View { |
} |
}; |
- createGraph(data) { |
+ createGraph(data, initiallyVisibileIds) { |
var g = this; |
g.nodes = data.nodes; |
g.nodeMap = []; |
@@ -298,6 +313,11 @@ class GraphView extends View { |
}); |
g.nodes.forEach(function(n, i) { |
n.visible = isNodeInitiallyVisible(n); |
+ if (initiallyVisibileIds != undefined) { |
+ if (initiallyVisibileIds.has(n.id)) { |
+ n.visible = true; |
+ } |
+ } |
}); |
g.fitGraphViewToWindow(); |
g.updateGraphVisibility(); |
@@ -306,6 +326,23 @@ class GraphView extends View { |
g.viewWholeGraph(); |
} |
+ connectVisibleSelectedNodes() { |
+ var graph = this; |
+ graph.state.selection.selection.forEach(function(element) { |
+ var edgeNumber = 0; |
+ element.__data__.inputs.forEach(function(edge) { |
+ if (edge.source.visible && edge.target.visible) { |
+ edge.visible = true; |
+ } |
+ }); |
+ element.__data__.outputs.forEach(function(edge) { |
+ if (edge.source.visible && edge.target.visible) { |
+ edge.visible = true; |
+ } |
+ }); |
+ }); |
+ } |
+ |
updateInputAndOutputBubbles() { |
var g = this; |
var s = g.visibleBubbles; |
@@ -359,11 +396,11 @@ class GraphView extends View { |
detachSelection() { |
var selection = this.state.selection.detachSelection(); |
- var result = new Set(); |
+ var s = new Set(); |
for (var i of selection) { |
- result.add(i.__data__.id); |
+ s.add(i.__data__.id); |
}; |
- return result; |
+ return s; |
} |
pathMouseDown(path, d) { |
@@ -436,6 +473,17 @@ class GraphView extends View { |
}); |
} |
+ selectAllNodes(inEdges, filter) { |
+ var graph = this; |
+ if (!d3.event.shiftKey) { |
+ graph.state.selection.clear(); |
+ } |
+ graph.visibleNodes.each(function(n) { |
+ graph.state.selection.select(this, true); |
+ }); |
+ graph.updateGraphVisibility(); |
+ } |
+ |
svgMouseDown() { |
this.state.graphMouseDown = true; |
} |
@@ -463,36 +511,109 @@ class GraphView extends View { |
// Don't handle key press repetition |
if(state.lastKeyDown !== -1) return; |
- var getEdgeFrontier = function(inEdges) { |
+ var getEdgeFrontier = function(inEdges, edgeFilter) { |
var frontierSet = new Set(); |
+ var newState = true; |
+ if (d3.event.ctrlKey) { |
+ state.selection.selection.forEach(function(element) { |
+ var edges = inEdges ? element.__data__.inputs : element.__data__.outputs; |
+ var edgeNumber = 0; |
+ // Control key toggles edges rather than just turning them on |
+ edges.forEach(function(i) { |
+ if (edgeFilter == undefined || edgeFilter(i, edgeNumber)) { |
+ if (i.visible) { |
+ newState = false; |
+ } |
+ } |
+ ++edgeNumber; |
+ }); |
+ }); |
+ } |
state.selection.selection.forEach(function(element) { |
- var nodes = inEdges ? element.__data__.inputs : element.__data__.outputs; |
- nodes.forEach(function(i) { |
- i.visible = true; |
- var candidate = inEdges ? i.source : i.target; |
- candidate.visible = true; |
- frontierSet.add(candidate); |
+ var edges = inEdges ? element.__data__.inputs : element.__data__.outputs; |
+ var edgeNumber = 0; |
+ edges.forEach(function(i) { |
+ if (edgeFilter == undefined || edgeFilter(i, edgeNumber)) { |
+ i.visible = newState; |
+ if (newState) { |
+ var candidate = inEdges ? i.source : i.target; |
+ candidate.visible = true; |
+ frontierSet.add(candidate); |
+ } |
+ } |
+ ++edgeNumber; |
}); |
}); |
graph.updateGraphVisibility(); |
- return graph.visibleNodes.filter(function(n) { |
- return frontierSet.has(n); |
- }); |
+ if (newState) { |
+ return graph.visibleNodes.filter(function(n) { |
+ return frontierSet.has(n); |
+ }); |
+ } else { |
+ return undefined; |
+ } |
+ } |
+ |
+ var selectNodesThroughEdges = function(inEdges, filter, reselect) { |
+ var frontier = getEdgeFrontier(inEdges, filter); |
+ if (frontier != undefined) { |
+ if (reselect) { |
+ if (!d3.event.shiftKey) { |
+ state.selection.clear(); |
+ } |
+ frontier.each(function(n) { |
+ state.selection.select(this, true); |
+ }); |
+ } |
+ graph.updateGraphVisibility(); |
+ } |
+ allowRepetition = false; |
} |
var allowRepetition = true; |
switch(d3.event.keyCode) { |
+ case 49: |
+ case 50: |
+ case 51: |
+ case 52: |
+ case 53: |
+ case 54: |
+ case 55: |
+ case 56: |
+ case 57: |
+ // '1'-'9' |
+ selectNodesThroughEdges(true, |
+ (edge, index) => { return index == (d3.event.keyCode - 49); }, |
+ false); |
+ break; |
+ case 67: |
+ // 'c' |
+ selectNodesThroughEdges(true, |
+ (edge, index) => { return edge.type == 'control'; }, |
+ false); |
+ break; |
+ case 69: |
+ // 'e' |
+ selectNodesThroughEdges(true, |
+ (edge, index) => { return edge.type == 'effect'; }, |
+ false); |
+ break; |
+ case 79: |
+ // 'o' |
+ selectNodesThroughEdges(false, undefined, false); |
+ break; |
+ case 73: |
+ // 'i' |
+ selectNodesThroughEdges(true, undefined, false); |
+ break; |
+ case 65: |
+ // 'a' |
+ graph.selectAllNodes(); |
+ allowRepetition = false; |
+ break; |
case 38: |
case 40: { |
- var frontier = getEdgeFrontier(d3.event.keyCode == 38); |
- if (!d3.event.shiftKey) { |
- state.selection.clear(); |
- } |
- frontier.each(function(n) { |
- state.selection.select(this, true); |
- }); |
- graph.updateGraphVisibility(); |
- allowRepetition = false; |
+ selectNodesThroughEdges(d3.event.keyCode == 38, undefined, true); |
break; |
} |
} |