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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 static get rectClass() { | 167 static get rectClass() { |
168 return "nodeStyle"; | 168 return "nodeStyle"; |
169 } | 169 } |
170 static get activeEditId() { | 170 static get activeEditId() { |
171 return "active-editing"; | 171 return "active-editing"; |
172 } | 172 } |
173 static get nodeRadius() { | 173 static get nodeRadius() { |
174 return 50; | 174 return 50; |
175 } | 175 } |
176 | 176 |
177 getNodeHeight(graph) { | 177 getNodeHeight(d) { |
178 if (this.state.showTypes) { | 178 if (this.state.showTypes) { |
179 return DEFAULT_NODE_HEIGHT + TYPE_HEIGHT; | 179 return d.normalheight + d.labelbbox.height; |
180 } else { | 180 } else { |
181 return DEFAULT_NODE_HEIGHT; | 181 return d.normalheight; |
182 } | 182 } |
183 } | 183 } |
184 | 184 |
185 getEdgeFrontier(nodes, inEdges, edgeFilter) { | 185 getEdgeFrontier(nodes, inEdges, edgeFilter) { |
186 let frontier = new Set(); | 186 let frontier = new Set(); |
187 nodes.forEach(function(element) { | 187 nodes.forEach(function(element) { |
188 var edges = inEdges ? element.__data__.inputs : element.__data__.outputs; | 188 var edges = inEdges ? element.__data__.inputs : element.__data__.outputs; |
189 var edgeNumber = 0; | 189 var edgeNumber = 0; |
190 edges.forEach(function(edge) { | 190 edges.forEach(function(edge) { |
191 if (edgeFilter == undefined || edgeFilter(edge, edgeNumber)) { | 191 if (edgeFilter == undefined || edgeFilter(edge, edgeNumber)) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 | 247 |
248 deleteContent() { | 248 deleteContent() { |
249 if (this.visibleNodes) { | 249 if (this.visibleNodes) { |
250 this.nodes = []; | 250 this.nodes = []; |
251 this.edges = []; | 251 this.edges = []; |
252 this.nodeMap = []; | 252 this.nodeMap = []; |
253 this.updateGraphVisibility(); | 253 this.updateGraphVisibility(); |
254 } | 254 } |
255 }; | 255 }; |
256 | 256 |
| 257 measureText(text) { |
| 258 var textMeasure = document.getElementById('text-measure'); |
| 259 textMeasure.textContent = text; |
| 260 return { |
| 261 width: textMeasure.getBBox().width, |
| 262 height: textMeasure.getBBox().height, |
| 263 }; |
| 264 } |
| 265 |
257 createGraph(data, initiallyVisibileIds) { | 266 createGraph(data, initiallyVisibileIds) { |
258 var g = this; | 267 var g = this; |
259 g.nodes = data.nodes; | 268 g.nodes = data.nodes; |
260 g.nodeMap = []; | 269 g.nodeMap = []; |
261 var textMeasure = document.getElementById('text-measure'); | |
262 g.nodes.forEach(function(n, i){ | 270 g.nodes.forEach(function(n, i){ |
263 n.__proto__ = Node; | 271 n.__proto__ = Node; |
264 n.visible = false; | 272 n.visible = false; |
265 n.x = 0; | 273 n.x = 0; |
266 n.y = 0; | 274 n.y = 0; |
267 n.rank = MAX_RANK_SENTINEL; | 275 n.rank = MAX_RANK_SENTINEL; |
268 n.inputs = []; | 276 n.inputs = []; |
269 n.outputs = []; | 277 n.outputs = []; |
270 n.rpo = -1; | 278 n.rpo = -1; |
271 n.outputApproach = MINIMUM_NODE_OUTPUT_APPROACH; | 279 n.outputApproach = MINIMUM_NODE_OUTPUT_APPROACH; |
272 n.cfg = n.control; | 280 n.cfg = n.control; |
273 g.nodeMap[n.id] = n; | 281 g.nodeMap[n.id] = n; |
274 n.displayLabel = n.getDisplayLabel(); | 282 n.displayLabel = n.getDisplayLabel(); |
275 textMeasure.textContent = n.getDisplayLabel(); | 283 n.labelbbox = g.measureText(n.displayLabel); |
276 var width = textMeasure.getComputedTextLength(); | 284 n.typebbox = g.measureText(n.getDisplayType()); |
277 textMeasure.textContent = n.getDisplayType(); | 285 var innerwidth = Math.max(n.labelbbox.width, n.typebbox.width); |
278 width = Math.max(width, textMeasure.getComputedTextLength()); | 286 n.width = Math.alignUp(innerwidth + NODE_INPUT_WIDTH * 2, |
279 n.width = Math.alignUp(width + NODE_INPUT_WIDTH * 2, | |
280 NODE_INPUT_WIDTH); | 287 NODE_INPUT_WIDTH); |
| 288 var innerheight = Math.max(n.labelbbox.height, n.typebbox.height); |
| 289 n.normalheight = innerheight + 20; |
281 }); | 290 }); |
282 g.edges = []; | 291 g.edges = []; |
283 data.edges.forEach(function(e, i){ | 292 data.edges.forEach(function(e, i){ |
284 var t = g.nodeMap[e.target]; | 293 var t = g.nodeMap[e.target]; |
285 var s = g.nodeMap[e.source]; | 294 var s = g.nodeMap[e.source]; |
286 var newEdge = new Edge(t, e.index, s, e.type); | 295 var newEdge = new Edge(t, e.index, s, e.type); |
287 t.inputs.push(newEdge); | 296 t.inputs.push(newEdge); |
288 s.outputs.push(newEdge); | 297 s.outputs.push(newEdge); |
289 g.edges.push(newEdge); | 298 g.edges.push(newEdge); |
290 if (e.type == 'control') { | 299 if (e.type == 'control') { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 return !edge.isVisible(); | 358 return !edge.isVisible(); |
350 } else { | 359 } else { |
351 return g.nodeMap[components[1]].areAnyOutputsVisible() == 0; | 360 return g.nodeMap[components[1]].areAnyOutputsVisible() == 0; |
352 } | 361 } |
353 }); | 362 }); |
354 s.each(function(c) { | 363 s.each(function(c) { |
355 var components = this.id.split(','); | 364 var components = this.id.split(','); |
356 if (components[0] == "ob") { | 365 if (components[0] == "ob") { |
357 var from = g.nodeMap[components[1]]; | 366 var from = g.nodeMap[components[1]]; |
358 var x = from.getOutputX(); | 367 var x = from.getOutputX(); |
359 var y = g.getNodeHeight() + DEFAULT_NODE_BUBBLE_RADIUS / 2 + 4; | 368 var y = g.getNodeHeight(from) + DEFAULT_NODE_BUBBLE_RADIUS; |
360 var transform = "translate(" + x + "," + y + ")"; | 369 var transform = "translate(" + x + "," + y + ")"; |
361 this.setAttribute('transform', transform); | 370 this.setAttribute('transform', transform); |
362 } | 371 } |
363 }); | 372 }); |
364 } | 373 } |
365 | 374 |
366 attachSelection(s) { | 375 attachSelection(s) { |
367 var graph = this; | 376 var graph = this; |
368 if (s.size != 0) { | 377 if (s.size != 0) { |
369 this.visibleNodes.each(function(n) { | 378 this.visibleNodes.each(function(n) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } | 468 } |
460 | 469 |
461 showAllAction(graph) { | 470 showAllAction(graph) { |
462 graph.nodes.filter(function(n) { n.visible = true; }) | 471 graph.nodes.filter(function(n) { n.visible = true; }) |
463 graph.edges.filter(function(e) { e.visible = true; }) | 472 graph.edges.filter(function(e) { e.visible = true; }) |
464 graph.updateGraphVisibility(); | 473 graph.updateGraphVisibility(); |
465 graph.viewWholeGraph(); | 474 graph.viewWholeGraph(); |
466 } | 475 } |
467 | 476 |
468 hideDeadAction(graph) { | 477 hideDeadAction(graph) { |
469 graph.nodes.filter(function(n) { if (!n.live) n.visible = false; }) | 478 graph.nodes.filter(function(n) { if (!n.isLive()) n.visible = false; }) |
470 graph.updateGraphVisibility(); | 479 graph.updateGraphVisibility(); |
471 } | 480 } |
472 | 481 |
473 hideUnselectedAction(graph) { | 482 hideUnselectedAction(graph) { |
474 var unselected = graph.visibleNodes.filter(function(n) { | 483 var unselected = graph.visibleNodes.filter(function(n) { |
475 return !this.classList.contains("selected"); | 484 return !this.classList.contains("selected"); |
476 }); | 485 }); |
477 unselected.each(function(n) { | 486 unselected.each(function(n) { |
478 n.visible = false; | 487 n.visible = false; |
479 }); | 488 }); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 graph.visibleEdges = visibleEdges; | 727 graph.visibleEdges = visibleEdges; |
719 | 728 |
720 // update existing nodes | 729 // update existing nodes |
721 var filteredNodes = graph.nodes.filter(function(n) { return n.visible; }); | 730 var filteredNodes = graph.nodes.filter(function(n) { return n.visible; }); |
722 graph.visibleNodes = graph.visibleNodes.data(filteredNodes, function(d) { | 731 graph.visibleNodes = graph.visibleNodes.data(filteredNodes, function(d) { |
723 return d.id; | 732 return d.id; |
724 }); | 733 }); |
725 graph.visibleNodes.attr("transform", function(n){ | 734 graph.visibleNodes.attr("transform", function(n){ |
726 return "translate(" + n.x + "," + n.y + ")"; | 735 return "translate(" + n.x + "," + n.y + ")"; |
727 }).select('rect'). | 736 }).select('rect'). |
728 attr(HEIGHT, function(d) { return graph.getNodeHeight(); }); | 737 attr(HEIGHT, function(d) { return graph.getNodeHeight(d); }); |
729 | 738 |
730 // add new nodes | 739 // add new nodes |
731 var newGs = graph.visibleNodes.enter() | 740 var newGs = graph.visibleNodes.enter() |
732 .append("g"); | 741 .append("g"); |
733 | 742 |
734 newGs.classed("control", function(n) { return n.isControl(); }) | 743 newGs.classed("control", function(n) { return n.isControl(); }) |
735 .classed("live", function(n) { return n.isLive(); }) | 744 .classed("live", function(n) { return n.isLive(); }) |
736 .classed("dead", function(n) { return !n.isLive(); }) | 745 .classed("dead", function(n) { return !n.isLive(); }) |
737 .classed("javascript", function(n) { return n.isJavaScript(); }) | 746 .classed("javascript", function(n) { return n.isJavaScript(); }) |
738 .classed("input", function(n) { return n.isInput(); }) | 747 .classed("input", function(n) { return n.isInput(); }) |
739 .classed("simplified", function(n) { return n.isSimplified(); }) | 748 .classed("simplified", function(n) { return n.isSimplified(); }) |
740 .classed("machine", function(n) { return n.isMachine(); }) | 749 .classed("machine", function(n) { return n.isMachine(); }) |
741 .attr("transform", function(d){ return "translate(" + d.x + "," + d.y + ")
";}) | 750 .attr("transform", function(d){ return "translate(" + d.x + "," + d.y + ")
";}) |
742 .on("mousedown", function(d){ | 751 .on("mousedown", function(d){ |
743 graph.nodeMouseDown.call(graph, d3.select(this), d); | 752 graph.nodeMouseDown.call(graph, d3.select(this), d); |
744 }) | 753 }) |
745 .on("mouseup", function(d){ | 754 .on("mouseup", function(d){ |
746 graph.nodeMouseUp.call(graph, d3.select(this), d); | 755 graph.nodeMouseUp.call(graph, d3.select(this), d); |
747 }) | 756 }) |
748 .call(graph.drag); | 757 .call(graph.drag); |
749 | 758 |
750 newGs.append("rect") | 759 newGs.append("rect") |
751 .attr("rx", 10) | 760 .attr("rx", 10) |
752 .attr("ry", 10) | 761 .attr("ry", 10) |
753 .attr(WIDTH, function(d) { return d.getTotalNodeWidth(); }) | 762 .attr(WIDTH, function(d) { |
754 .attr(HEIGHT, function(d) { return graph.getNodeHeight(); }) | 763 return d.getTotalNodeWidth(); |
| 764 }) |
| 765 .attr(HEIGHT, function(d) { |
| 766 return graph.getNodeHeight(d); |
| 767 }) |
755 | 768 |
756 function appendInputAndOutputBubbles(g, d) { | 769 function appendInputAndOutputBubbles(g, d) { |
757 for (var i = 0; i < d.inputs.length; ++i) { | 770 for (var i = 0; i < d.inputs.length; ++i) { |
758 var x = d.getInputX(i); | 771 var x = d.getInputX(i); |
759 var y = -DEFAULT_NODE_BUBBLE_RADIUS / 2 - 4; | 772 var y = -DEFAULT_NODE_BUBBLE_RADIUS; |
760 var s = g.append('circle') | 773 var s = g.append('circle') |
761 .classed("filledBubbleStyle", function(c) { | 774 .classed("filledBubbleStyle", function(c) { |
762 return d.inputs[i].isVisible(); | 775 return d.inputs[i].isVisible(); |
763 } ) | 776 } ) |
764 .classed("bubbleStyle", function(c) { | 777 .classed("bubbleStyle", function(c) { |
765 return !d.inputs[i].isVisible(); | 778 return !d.inputs[i].isVisible(); |
766 } ) | 779 } ) |
767 .attr("id", "ib," + d.inputs[i].stringID()) | 780 .attr("id", "ib," + d.inputs[i].stringID()) |
768 .attr("r", DEFAULT_NODE_BUBBLE_RADIUS) | 781 .attr("r", DEFAULT_NODE_BUBBLE_RADIUS) |
769 .attr("transform", function(d) { | 782 .attr("transform", function(d) { |
770 return "translate(" + x + "," + y + ")"; | 783 return "translate(" + x + "," + y + ")"; |
771 }) | 784 }) |
772 .on("mousedown", function(d){ | 785 .on("mousedown", function(d){ |
773 var components = this.id.split(','); | 786 var components = this.id.split(','); |
774 var node = graph.nodeMap[components[3]]; | 787 var node = graph.nodeMap[components[3]]; |
775 var edge = node.inputs[components[2]]; | 788 var edge = node.inputs[components[2]]; |
776 var visible = !edge.isVisible(); | 789 var visible = !edge.isVisible(); |
777 node.setInputVisibility(components[2], visible); | 790 node.setInputVisibility(components[2], visible); |
778 d3.event.stopPropagation(); | 791 d3.event.stopPropagation(); |
779 graph.updateGraphVisibility(); | 792 graph.updateGraphVisibility(); |
780 }); | 793 }); |
781 } | 794 } |
782 if (d.outputs.length != 0) { | 795 if (d.outputs.length != 0) { |
783 var x = d.getOutputX(); | 796 var x = d.getOutputX(); |
784 var y = graph.getNodeHeight() + DEFAULT_NODE_BUBBLE_RADIUS / 2 + 4; | 797 var y = graph.getNodeHeight(d) + DEFAULT_NODE_BUBBLE_RADIUS; |
785 var s = g.append('circle') | 798 var s = g.append('circle') |
786 .classed("filledBubbleStyle", function(c) { | 799 .classed("filledBubbleStyle", function(c) { |
787 return d.areAnyOutputsVisible() == 2; | 800 return d.areAnyOutputsVisible() == 2; |
788 } ) | 801 } ) |
789 .classed("halFilledBubbleStyle", function(c) { | 802 .classed("halFilledBubbleStyle", function(c) { |
790 return d.areAnyOutputsVisible() == 1; | 803 return d.areAnyOutputsVisible() == 1; |
791 } ) | 804 } ) |
792 .classed("bubbleStyle", function(c) { | 805 .classed("bubbleStyle", function(c) { |
793 return d.areAnyOutputsVisible() == 0; | 806 return d.areAnyOutputsVisible() == 0; |
794 } ) | 807 } ) |
(...skipping 11 matching lines...) Expand all Loading... |
806 } | 819 } |
807 | 820 |
808 newGs.each(function(d){ | 821 newGs.each(function(d){ |
809 appendInputAndOutputBubbles(d3.select(this), d); | 822 appendInputAndOutputBubbles(d3.select(this), d); |
810 }); | 823 }); |
811 | 824 |
812 newGs.each(function(d){ | 825 newGs.each(function(d){ |
813 d3.select(this).append("text") | 826 d3.select(this).append("text") |
814 .classed("label", true) | 827 .classed("label", true) |
815 .attr("text-anchor","right") | 828 .attr("text-anchor","right") |
816 .attr("dx", "5") | 829 .attr("dx", 5) |
817 .attr("dy", DEFAULT_NODE_HEIGHT / 2 + 5) | 830 .attr("dy", 5) |
818 .append('tspan') | 831 .append('tspan') |
819 .text(function(l) { | 832 .text(function(l) { |
820 return d.getDisplayLabel(); | 833 return d.getDisplayLabel(); |
821 }) | 834 }) |
822 .append("title") | 835 .append("title") |
823 .text(function(l) { | 836 .text(function(l) { |
824 return d.getTitle(); | 837 return d.getTitle(); |
825 }) | 838 }) |
826 if (d.type != undefined) { | 839 if (d.type != undefined) { |
827 d3.select(this).append("text") | 840 d3.select(this).append("text") |
828 .classed("label", true) | 841 .classed("label", true) |
829 .classed("type", true) | 842 .classed("type", true) |
830 .attr("text-anchor","right") | 843 .attr("text-anchor","right") |
831 .attr("dx", "5") | 844 .attr("dx", 5) |
832 .attr("dy", DEFAULT_NODE_HEIGHT / 2 + TYPE_HEIGHT + 5) | 845 .attr("dy", d.labelbbox.height + 5) |
833 .append('tspan') | 846 .append('tspan') |
834 .text(function(l) { | 847 .text(function(l) { |
835 return d.getDisplayType(); | 848 return d.getDisplayType(); |
836 }) | 849 }) |
837 .append("title") | 850 .append("title") |
838 .text(function(l) { | 851 .text(function(l) { |
839 return d.getType(); | 852 return d.getType(); |
840 }) | 853 }) |
841 } | 854 } |
842 }); | 855 }); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 var graph = this; | 992 var graph = this; |
980 var minX, maxX, minY, maxY; | 993 var minX, maxX, minY, maxY; |
981 var hasSelection = false; | 994 var hasSelection = false; |
982 graph.visibleNodes.each(function(n) { | 995 graph.visibleNodes.each(function(n) { |
983 if (this.classList.contains("selected")) { | 996 if (this.classList.contains("selected")) { |
984 hasSelection = true; | 997 hasSelection = true; |
985 minX = minX ? Math.min(minX, n.x) : n.x; | 998 minX = minX ? Math.min(minX, n.x) : n.x; |
986 maxX = maxX ? Math.max(maxX, n.x + n.getTotalNodeWidth()) : | 999 maxX = maxX ? Math.max(maxX, n.x + n.getTotalNodeWidth()) : |
987 n.x + n.getTotalNodeWidth(); | 1000 n.x + n.getTotalNodeWidth(); |
988 minY = minY ? Math.min(minY, n.y) : n.y; | 1001 minY = minY ? Math.min(minY, n.y) : n.y; |
989 maxY = maxY ? Math.max(maxY, n.y + DEFAULT_NODE_HEIGHT) : | 1002 maxY = maxY ? Math.max(maxY, n.y + graph.getNodeHeight(n)) : |
990 n.y + DEFAULT_NODE_HEIGHT; | 1003 n.y + graph.getNodeHeight(n); |
991 } | 1004 } |
992 }); | 1005 }); |
993 if (hasSelection) { | 1006 if (hasSelection) { |
994 graph.viewGraphRegion(minX - NODE_INPUT_WIDTH, minY - 60, | 1007 graph.viewGraphRegion(minX - NODE_INPUT_WIDTH, minY - 60, |
995 maxX + NODE_INPUT_WIDTH, maxY + 60, | 1008 maxX + NODE_INPUT_WIDTH, maxY + 60, |
996 true); | 1009 true); |
997 } | 1010 } |
998 } | 1011 } |
999 | 1012 |
1000 viewGraphRegion(minX, minY, maxX, maxY, transition) { | 1013 viewGraphRegion(minX, minY, maxX, maxY, transition) { |
(...skipping 10 matching lines...) Expand all Loading... |
1011 } | 1024 } |
1012 | 1025 |
1013 viewWholeGraph() { | 1026 viewWholeGraph() { |
1014 var graph = this; | 1027 var graph = this; |
1015 var minScale = graph.minScale(); | 1028 var minScale = graph.minScale(); |
1016 var translation = [0, 0]; | 1029 var translation = [0, 0]; |
1017 translation = graph.getVisibleTranslation(translation, minScale); | 1030 translation = graph.getVisibleTranslation(translation, minScale); |
1018 graph.translateClipped(translation, minScale); | 1031 graph.translateClipped(translation, minScale); |
1019 } | 1032 } |
1020 } | 1033 } |
OLD | NEW |