• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import { GNode, MINIMUM_EDGE_SEPARATION } from "./node";
2import { Edge } from "./edge";
3
4export class Graph {
5  nodeMap: Array<GNode>;
6  minGraphX: number;
7  maxGraphX: number;
8  minGraphY: number;
9  maxGraphY: number;
10  maxGraphNodeX: number;
11  maxBackEdgeNumber: number;
12  width: number;
13  height: number;
14
15  constructor(data: any) {
16    this.nodeMap = [];
17
18    this.minGraphX = 0;
19    this.maxGraphX = 1;
20    this.minGraphY = 0;
21    this.maxGraphY = 1;
22    this.width = 1;
23    this.height = 1;
24
25    data.nodes.forEach((jsonNode: any) => {
26      this.nodeMap[jsonNode.id] = new GNode(jsonNode.nodeLabel);
27    });
28
29    data.edges.forEach((e: any) => {
30      const t = this.nodeMap[e.target];
31      const s = this.nodeMap[e.source];
32      const newEdge = new Edge(t, e.index, s, e.type);
33      t.inputs.push(newEdge);
34      s.outputs.push(newEdge);
35      if (e.type == 'control') {
36        // Every source of a control edge is a CFG node.
37        s.cfg = true;
38      }
39    });
40
41  }
42
43  *nodes(p = (n: GNode) => true) {
44    for (const node of this.nodeMap) {
45      if (!node || !p(node)) continue;
46      yield node;
47    }
48  }
49
50  *filteredEdges(p: (e: Edge) => boolean) {
51    for (const node of this.nodes()) {
52      for (const edge of node.inputs) {
53        if (p(edge)) yield edge;
54      }
55    }
56  }
57
58  forEachEdge(p: (e: Edge) => void) {
59    for (const node of this.nodeMap) {
60      if (!node) continue;
61      for (const edge of node.inputs) {
62        p(edge);
63      }
64    }
65  }
66
67  redetermineGraphBoundingBox(showTypes: boolean): [[number, number], [number, number]] {
68    this.minGraphX = 0;
69    this.maxGraphNodeX = 1;
70    this.maxGraphX = undefined;  // see below
71    this.minGraphY = 0;
72    this.maxGraphY = 1;
73
74    for (const node of this.nodes()) {
75      if (!node.visible) {
76        continue;
77      }
78
79      if (node.x < this.minGraphX) {
80        this.minGraphX = node.x;
81      }
82      if ((node.x + node.getTotalNodeWidth()) > this.maxGraphNodeX) {
83        this.maxGraphNodeX = node.x + node.getTotalNodeWidth();
84      }
85      if ((node.y - 50) < this.minGraphY) {
86        this.minGraphY = node.y - 50;
87      }
88      if ((node.y + node.getNodeHeight(showTypes) + 50) > this.maxGraphY) {
89        this.maxGraphY = node.y + node.getNodeHeight(showTypes) + 50;
90      }
91    }
92
93    this.maxGraphX = this.maxGraphNodeX +
94      this.maxBackEdgeNumber * MINIMUM_EDGE_SEPARATION;
95
96    this.width = this.maxGraphX - this.minGraphX;
97    this.height = this.maxGraphY - this.minGraphY;
98
99    const extent: [[number, number], [number, number]] = [
100      [this.minGraphX - this.width / 2, this.minGraphY - this.height / 2],
101      [this.maxGraphX + this.width / 2, this.maxGraphY + this.height / 2]
102    ];
103
104    return extent;
105  }
106
107}
108