| 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 |