1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import { GNode, MINIMUM_EDGE_SEPARATION, DEFAULT_NODE_BUBBLE_RADIUS } from "../src/node"; 6import { Graph } from "./graph"; 7 8const BEZIER_CONSTANT = 0.3; 9 10export class Edge { 11 target: GNode; 12 source: GNode; 13 index: number; 14 type: string; 15 backEdgeNumber: number; 16 visible: boolean; 17 18 constructor(target: GNode, index: number, source: GNode, type: string) { 19 this.target = target; 20 this.source = source; 21 this.index = index; 22 this.type = type; 23 this.backEdgeNumber = 0; 24 this.visible = false; 25 } 26 27 stringID() { 28 return this.source.id + "," + this.index + "," + this.target.id; 29 } 30 31 isVisible() { 32 return this.visible && this.source.visible && this.target.visible; 33 } 34 35 getInputHorizontalPosition(graph: Graph, showTypes: boolean) { 36 if (this.backEdgeNumber > 0) { 37 return graph.maxGraphNodeX + this.backEdgeNumber * MINIMUM_EDGE_SEPARATION; 38 } 39 const source = this.source; 40 const target = this.target; 41 const index = this.index; 42 const inputX = target.x + target.getInputX(index); 43 const inputApproach = target.getInputApproach(this.index); 44 const outputApproach = source.getOutputApproach(showTypes); 45 if (inputApproach > outputApproach) { 46 return inputX; 47 } else { 48 const inputOffset = MINIMUM_EDGE_SEPARATION * (index + 1); 49 return (target.x < source.x) 50 ? (target.x + target.getTotalNodeWidth() + inputOffset) 51 : (target.x - inputOffset); 52 } 53 } 54 55 generatePath(graph: Graph, showTypes: boolean) { 56 const target = this.target; 57 const source = this.source; 58 const inputX = target.x + target.getInputX(this.index); 59 const arrowheadHeight = 7; 60 const inputY = target.y - 2 * DEFAULT_NODE_BUBBLE_RADIUS - arrowheadHeight; 61 const outputX = source.x + source.getOutputX(); 62 const outputY = source.y + source.getNodeHeight(showTypes) + DEFAULT_NODE_BUBBLE_RADIUS; 63 let inputApproach = target.getInputApproach(this.index); 64 const outputApproach = source.getOutputApproach(showTypes); 65 const horizontalPos = this.getInputHorizontalPosition(graph, showTypes); 66 67 let result: string; 68 69 if (inputY < outputY) { 70 result = `M ${outputX} ${outputY} 71 L ${outputX} ${outputApproach} 72 L ${horizontalPos} ${outputApproach}`; 73 74 if (horizontalPos != inputX) { 75 result += `L ${horizontalPos} ${inputApproach}`; 76 } else { 77 if (inputApproach < outputApproach) { 78 inputApproach = outputApproach; 79 } 80 } 81 82 result += `L ${inputX} ${inputApproach} 83 L ${inputX} ${inputY}`; 84 } else { 85 const controlY = outputY + (inputY - outputY) * BEZIER_CONSTANT; 86 result = `M ${outputX} ${outputY} 87 C ${outputX} ${controlY}, 88 ${inputX} ${outputY}, 89 ${inputX} ${inputY}`; 90 } 91 92 return result; 93 } 94 95 isBackEdge() { 96 return this.target.hasBackEdges() && (this.target.rank < this.source.rank); 97 } 98 99} 100 101export const edgeToStr = (e: Edge) => e.stringID(); 102