OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 "use strict"; | 5 "use strict"; |
6 | 6 |
7 class GraphView extends View { | 7 class GraphView extends View { |
8 constructor (d3, id, nodes, edges, broker) { | 8 constructor (d3, id, nodes, edges, broker) { |
9 super(id, broker); | 9 super(id, broker); |
10 var graph = this; | 10 var graph = this; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 }); | 166 }); |
167 | 167 |
168 d3.select("#toggle-types").on("click", function() { | 168 d3.select("#toggle-types").on("click", function() { |
169 graph.toggleTypes(); | 169 graph.toggleTypes(); |
170 }); | 170 }); |
171 | 171 |
172 d3.select("#search-input").on("keydown", function() { | 172 d3.select("#search-input").on("keydown", function() { |
173 if (d3.event.keyCode == 13) { | 173 if (d3.event.keyCode == 13) { |
174 graph.state.selection.clear(); | 174 graph.state.selection.clear(); |
175 var reg = new RegExp(this.value); | 175 var reg = new RegExp(this.value); |
| 176 var filterFunction = function(n) { |
| 177 return (reg.exec(n.getDisplayLabel()) != null || |
| 178 (graph.state.showTypes && reg.exec(n.getDisplayType())) || |
| 179 reg.exec(n.opcode) != null); |
| 180 }; |
| 181 if (d3.event.ctrlKey) { |
| 182 graph.nodes.forEach(function(n, i) { |
| 183 if (filterFunction(n)) { |
| 184 n.visible = true; |
| 185 } |
| 186 }); |
| 187 graph.updateGraphVisibility(); |
| 188 } |
176 var selected = graph.visibleNodes.each(function(n) { | 189 var selected = graph.visibleNodes.each(function(n) { |
177 if (reg.exec(n.getDisplayLabel()) != null || | 190 if (filterFunction(n)) { |
178 (graph.state.showTypes && reg.exec(n.getDisplayType())) || | |
179 reg.exec(n.opcode) != null) { | |
180 graph.state.selection.select(this, true); | 191 graph.state.selection.select(this, true); |
181 } | 192 } |
182 }); | 193 }); |
| 194 graph.connectVisibleSelectedNodes(); |
| 195 graph.updateGraphVisibility(); |
183 this.blur(); | 196 this.blur(); |
184 graph.viewSelection(); | 197 graph.viewSelection(); |
185 } | 198 } |
| 199 d3.event.stopPropagation(); |
186 }); | 200 }); |
187 | 201 |
188 // listen for key events | 202 // listen for key events |
189 d3.select(window).on("keydown", function(e){ | 203 d3.select(window).on("keydown", function(e){ |
190 graph.svgKeyDown.call(graph); | 204 graph.svgKeyDown.call(graph); |
191 }) | 205 }) |
192 .on("keyup", function(){ | 206 .on("keyup", function(){ |
193 graph.svgKeyUp.call(graph); | 207 graph.svgKeyUp.call(graph); |
194 }); | 208 }); |
195 svg.on("mousedown", function(d){graph.svgMouseDown.call(graph, d);}); | 209 svg.on("mousedown", function(d){graph.svgMouseDown.call(graph, d);}); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 } | 250 } |
237 | 251 |
238 dragmove(d) { | 252 dragmove(d) { |
239 var graph = this; | 253 var graph = this; |
240 d.x += d3.event.dx; | 254 d.x += d3.event.dx; |
241 d.y += d3.event.dy; | 255 d.y += d3.event.dy; |
242 graph.updateGraphVisibility(); | 256 graph.updateGraphVisibility(); |
243 } | 257 } |
244 | 258 |
245 initializeContent(data, rememberedSelection) { | 259 initializeContent(data, rememberedSelection) { |
246 this.createGraph(data); | 260 this.createGraph(data, rememberedSelection); |
247 if (rememberedSelection != null) { | 261 if (rememberedSelection != null) { |
248 this.attachSelection(rememberedSelection); | 262 this.attachSelection(rememberedSelection); |
| 263 this.connectVisibleSelectedNodes(); |
249 } | 264 } |
250 this.updateGraphVisibility(); | 265 this.updateGraphVisibility(); |
251 } | 266 } |
252 | 267 |
253 deleteContent() { | 268 deleteContent() { |
254 if (this.visibleNodes) { | 269 if (this.visibleNodes) { |
255 this.nodes = []; | 270 this.nodes = []; |
256 this.edges = []; | 271 this.edges = []; |
257 this.nodeMap = []; | 272 this.nodeMap = []; |
258 this.updateGraphVisibility(); | 273 this.updateGraphVisibility(); |
259 } | 274 } |
260 }; | 275 }; |
261 | 276 |
262 createGraph(data) { | 277 createGraph(data, initiallyVisibileIds) { |
263 var g = this; | 278 var g = this; |
264 g.nodes = data.nodes; | 279 g.nodes = data.nodes; |
265 g.nodeMap = []; | 280 g.nodeMap = []; |
266 var textMeasure = document.getElementById('text-measure'); | 281 var textMeasure = document.getElementById('text-measure'); |
267 g.nodes.forEach(function(n, i){ | 282 g.nodes.forEach(function(n, i){ |
268 n.__proto__ = Node; | 283 n.__proto__ = Node; |
269 n.visible = false; | 284 n.visible = false; |
270 n.x = 0; | 285 n.x = 0; |
271 n.y = 0; | 286 n.y = 0; |
272 n.rank = MAX_RANK_SENTINEL; | 287 n.rank = MAX_RANK_SENTINEL; |
(...skipping 18 matching lines...) Expand all Loading... |
291 var newEdge = new Edge(t, e.index, s, e.type); | 306 var newEdge = new Edge(t, e.index, s, e.type); |
292 t.inputs.push(newEdge); | 307 t.inputs.push(newEdge); |
293 s.outputs.push(newEdge); | 308 s.outputs.push(newEdge); |
294 g.edges.push(newEdge); | 309 g.edges.push(newEdge); |
295 if (e.type == 'control') { | 310 if (e.type == 'control') { |
296 s.cfg = true; | 311 s.cfg = true; |
297 } | 312 } |
298 }); | 313 }); |
299 g.nodes.forEach(function(n, i) { | 314 g.nodes.forEach(function(n, i) { |
300 n.visible = isNodeInitiallyVisible(n); | 315 n.visible = isNodeInitiallyVisible(n); |
| 316 if (initiallyVisibileIds != undefined) { |
| 317 if (initiallyVisibileIds.has(n.id)) { |
| 318 n.visible = true; |
| 319 } |
| 320 } |
301 }); | 321 }); |
302 g.fitGraphViewToWindow(); | 322 g.fitGraphViewToWindow(); |
303 g.updateGraphVisibility(); | 323 g.updateGraphVisibility(); |
304 g.layoutGraph(); | 324 g.layoutGraph(); |
305 g.updateGraphVisibility(); | 325 g.updateGraphVisibility(); |
306 g.viewWholeGraph(); | 326 g.viewWholeGraph(); |
307 } | 327 } |
308 | 328 |
| 329 connectVisibleSelectedNodes() { |
| 330 var graph = this; |
| 331 graph.state.selection.selection.forEach(function(element) { |
| 332 var edgeNumber = 0; |
| 333 element.__data__.inputs.forEach(function(edge) { |
| 334 if (edge.source.visible && edge.target.visible) { |
| 335 edge.visible = true; |
| 336 } |
| 337 }); |
| 338 element.__data__.outputs.forEach(function(edge) { |
| 339 if (edge.source.visible && edge.target.visible) { |
| 340 edge.visible = true; |
| 341 } |
| 342 }); |
| 343 }); |
| 344 } |
| 345 |
309 updateInputAndOutputBubbles() { | 346 updateInputAndOutputBubbles() { |
310 var g = this; | 347 var g = this; |
311 var s = g.visibleBubbles; | 348 var s = g.visibleBubbles; |
312 s.classed("filledBubbleStyle", function(c) { | 349 s.classed("filledBubbleStyle", function(c) { |
313 var components = this.id.split(','); | 350 var components = this.id.split(','); |
314 if (components[0] == "ib") { | 351 if (components[0] == "ib") { |
315 var edge = g.nodeMap[components[3]].inputs[components[2]]; | 352 var edge = g.nodeMap[components[3]].inputs[components[2]]; |
316 return edge.isVisible(); | 353 return edge.isVisible(); |
317 } else { | 354 } else { |
318 return g.nodeMap[components[1]].areAnyOutputsVisible() == 2; | 355 return g.nodeMap[components[1]].areAnyOutputsVisible() == 2; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 this.visibleNodes.each(function(n) { | 389 this.visibleNodes.each(function(n) { |
353 if (s.has(this.__data__.id)) { | 390 if (s.has(this.__data__.id)) { |
354 graph.state.selection.select(this, true); | 391 graph.state.selection.select(this, true); |
355 } | 392 } |
356 }); | 393 }); |
357 } | 394 } |
358 } | 395 } |
359 | 396 |
360 detachSelection() { | 397 detachSelection() { |
361 var selection = this.state.selection.detachSelection(); | 398 var selection = this.state.selection.detachSelection(); |
362 var result = new Set(); | 399 var s = new Set(); |
363 for (var i of selection) { | 400 for (var i of selection) { |
364 result.add(i.__data__.id); | 401 s.add(i.__data__.id); |
365 }; | 402 }; |
366 return result; | 403 return s; |
367 } | 404 } |
368 | 405 |
369 pathMouseDown(path, d) { | 406 pathMouseDown(path, d) { |
370 d3.event.stopPropagation(); | 407 d3.event.stopPropagation(); |
371 this.state.selection.clear(); | 408 this.state.selection.clear(); |
372 this.state.selection.add(path); | 409 this.state.selection.add(path); |
373 }; | 410 }; |
374 | 411 |
375 nodeMouseDown(node, d) { | 412 nodeMouseDown(node, d) { |
376 d3.event.stopPropagation(); | 413 d3.event.stopPropagation(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 } | 466 } |
430 }); | 467 }); |
431 graph.updateGraphVisibility(); | 468 graph.updateGraphVisibility(); |
432 graph.visibleNodes.filter(function(n) { return map[n.id]; }) | 469 graph.visibleNodes.filter(function(n) { return map[n.id]; }) |
433 .each(function(n) { | 470 .each(function(n) { |
434 var selection = graph.state.selection; | 471 var selection = graph.state.selection; |
435 selection.select(d3.select(this), selected); | 472 selection.select(d3.select(this), selected); |
436 }); | 473 }); |
437 } | 474 } |
438 | 475 |
| 476 selectAllNodes(inEdges, filter) { |
| 477 var graph = this; |
| 478 if (!d3.event.shiftKey) { |
| 479 graph.state.selection.clear(); |
| 480 } |
| 481 graph.visibleNodes.each(function(n) { |
| 482 graph.state.selection.select(this, true); |
| 483 }); |
| 484 graph.updateGraphVisibility(); |
| 485 } |
| 486 |
439 svgMouseDown() { | 487 svgMouseDown() { |
440 this.state.graphMouseDown = true; | 488 this.state.graphMouseDown = true; |
441 } | 489 } |
442 | 490 |
443 svgMouseUp() { | 491 svgMouseUp() { |
444 var graph = this, | 492 var graph = this, |
445 state = graph.state; | 493 state = graph.state; |
446 if (state.justScaleTransGraph) { | 494 if (state.justScaleTransGraph) { |
447 // Dragged | 495 // Dragged |
448 state.justScaleTransGraph = false; | 496 state.justScaleTransGraph = false; |
449 } else { | 497 } else { |
450 // Clicked | 498 // Clicked |
451 if (state.mouseDownNode == null) { | 499 if (state.mouseDownNode == null) { |
452 graph.state.selection.clear(); | 500 graph.state.selection.clear(); |
453 } | 501 } |
454 } | 502 } |
455 state.mouseDownNode = null; | 503 state.mouseDownNode = null; |
456 state.graphMouseDown = false; | 504 state.graphMouseDown = false; |
457 } | 505 } |
458 | 506 |
459 svgKeyDown() { | 507 svgKeyDown() { |
460 var state = this.state; | 508 var state = this.state; |
461 var graph = this; | 509 var graph = this; |
462 | 510 |
463 // Don't handle key press repetition | 511 // Don't handle key press repetition |
464 if(state.lastKeyDown !== -1) return; | 512 if(state.lastKeyDown !== -1) return; |
465 | 513 |
466 var getEdgeFrontier = function(inEdges) { | 514 var getEdgeFrontier = function(inEdges, edgeFilter) { |
467 var frontierSet = new Set(); | 515 var frontierSet = new Set(); |
| 516 var newState = true; |
| 517 if (d3.event.ctrlKey) { |
| 518 state.selection.selection.forEach(function(element) { |
| 519 var edges = inEdges ? element.__data__.inputs : element.__data__.outpu
ts; |
| 520 var edgeNumber = 0; |
| 521 // Control key toggles edges rather than just turning them on |
| 522 edges.forEach(function(i) { |
| 523 if (edgeFilter == undefined || edgeFilter(i, edgeNumber)) { |
| 524 if (i.visible) { |
| 525 newState = false; |
| 526 } |
| 527 } |
| 528 ++edgeNumber; |
| 529 }); |
| 530 }); |
| 531 } |
468 state.selection.selection.forEach(function(element) { | 532 state.selection.selection.forEach(function(element) { |
469 var nodes = inEdges ? element.__data__.inputs : element.__data__.outputs
; | 533 var edges = inEdges ? element.__data__.inputs : element.__data__.outputs
; |
470 nodes.forEach(function(i) { | 534 var edgeNumber = 0; |
471 i.visible = true; | 535 edges.forEach(function(i) { |
472 var candidate = inEdges ? i.source : i.target; | 536 if (edgeFilter == undefined || edgeFilter(i, edgeNumber)) { |
473 candidate.visible = true; | 537 i.visible = newState; |
474 frontierSet.add(candidate); | 538 if (newState) { |
| 539 var candidate = inEdges ? i.source : i.target; |
| 540 candidate.visible = true; |
| 541 frontierSet.add(candidate); |
| 542 } |
| 543 } |
| 544 ++edgeNumber; |
475 }); | 545 }); |
476 }); | 546 }); |
477 graph.updateGraphVisibility(); | 547 graph.updateGraphVisibility(); |
478 return graph.visibleNodes.filter(function(n) { | 548 if (newState) { |
479 return frontierSet.has(n); | 549 return graph.visibleNodes.filter(function(n) { |
480 }); | 550 return frontierSet.has(n); |
| 551 }); |
| 552 } else { |
| 553 return undefined; |
| 554 } |
| 555 } |
| 556 |
| 557 var selectNodesThroughEdges = function(inEdges, filter, reselect) { |
| 558 var frontier = getEdgeFrontier(inEdges, filter); |
| 559 if (frontier != undefined) { |
| 560 if (reselect) { |
| 561 if (!d3.event.shiftKey) { |
| 562 state.selection.clear(); |
| 563 } |
| 564 frontier.each(function(n) { |
| 565 state.selection.select(this, true); |
| 566 }); |
| 567 } |
| 568 graph.updateGraphVisibility(); |
| 569 } |
| 570 allowRepetition = false; |
481 } | 571 } |
482 | 572 |
483 var allowRepetition = true; | 573 var allowRepetition = true; |
484 switch(d3.event.keyCode) { | 574 switch(d3.event.keyCode) { |
| 575 case 49: |
| 576 case 50: |
| 577 case 51: |
| 578 case 52: |
| 579 case 53: |
| 580 case 54: |
| 581 case 55: |
| 582 case 56: |
| 583 case 57: |
| 584 // '1'-'9' |
| 585 selectNodesThroughEdges(true, |
| 586 (edge, index) => { return index == (d3.event.keyCo
de - 49); }, |
| 587 false); |
| 588 break; |
| 589 case 67: |
| 590 // 'c' |
| 591 selectNodesThroughEdges(true, |
| 592 (edge, index) => { return edge.type == 'control';
}, |
| 593 false); |
| 594 break; |
| 595 case 69: |
| 596 // 'e' |
| 597 selectNodesThroughEdges(true, |
| 598 (edge, index) => { return edge.type == 'effect'; }
, |
| 599 false); |
| 600 break; |
| 601 case 79: |
| 602 // 'o' |
| 603 selectNodesThroughEdges(false, undefined, false); |
| 604 break; |
| 605 case 73: |
| 606 // 'i' |
| 607 selectNodesThroughEdges(true, undefined, false); |
| 608 break; |
| 609 case 65: |
| 610 // 'a' |
| 611 graph.selectAllNodes(); |
| 612 allowRepetition = false; |
| 613 break; |
485 case 38: | 614 case 38: |
486 case 40: { | 615 case 40: { |
487 var frontier = getEdgeFrontier(d3.event.keyCode == 38); | 616 selectNodesThroughEdges(d3.event.keyCode == 38, undefined, true); |
488 if (!d3.event.shiftKey) { | |
489 state.selection.clear(); | |
490 } | |
491 frontier.each(function(n) { | |
492 state.selection.select(this, true); | |
493 }); | |
494 graph.updateGraphVisibility(); | |
495 allowRepetition = false; | |
496 break; | 617 break; |
497 } | 618 } |
498 } | 619 } |
499 if (!allowRepetition) { | 620 if (!allowRepetition) { |
500 state.lastKeyDown = d3.event.keyCode; | 621 state.lastKeyDown = d3.event.keyCode; |
501 } | 622 } |
502 } | 623 } |
503 | 624 |
504 svgKeyUp() { | 625 svgKeyUp() { |
505 this.state.lastKeyDown = -1 | 626 this.state.lastKeyDown = -1 |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 } | 972 } |
852 | 973 |
853 viewWholeGraph() { | 974 viewWholeGraph() { |
854 var graph = this; | 975 var graph = this; |
855 var minScale = graph.minScale(); | 976 var minScale = graph.minScale(); |
856 var translation = [0, 0]; | 977 var translation = [0, 0]; |
857 translation = graph.getVisibleTranslation(translation, minScale); | 978 translation = graph.getVisibleTranslation(translation, minScale); |
858 graph.translateClipped(translation, minScale); | 979 graph.translateClipped(translation, minScale); |
859 } | 980 } |
860 } | 981 } |
OLD | NEW |