| 36 | public abstract svgKeyDown(): void; |
| 37 | |
| 38 | constructor(idOrContainer: string | HTMLElement, broker: SelectionBroker, |
| 39 | showPhaseByName: (name: string, selection: SelectionStorage) => void, |
| 40 | toolbox: HTMLElement) { |
| 41 | super(idOrContainer); |
| 42 | this.broker = broker; |
| 43 | this.showPhaseByName = showPhaseByName; |
| 44 | this.toolbox = toolbox; |
| 45 | this.state = new MovableViewState(); |
| 46 | this.divElement = d3.select(this.divNode); |
| 47 | |
| 48 | // Listen for key events. Note that the focus handler seems |
| 49 | // to be important even if it does nothing. |
| 50 | this.svg = this.divElement.append("svg") |
| 51 | .attr("version", "2.0") |
| 52 | .attr("width", "100%") |
| 53 | .attr("height", "100%") |
| 54 | .on("focus", () => { }) |
| 55 | .on("keydown", () => this.svgKeyDown()); |
| 56 | |
| 57 | this.svg.append("svg:defs") |
| 58 | .append("svg:marker") |
| 59 | .attr("id", "end-arrow") |
| 60 | .attr("viewBox", "0 -4 8 8") |
| 61 | .attr("refX", 2) |
| 62 | .attr("markerWidth", 2.5) |
| 63 | .attr("markerHeight", 2.5) |
| 64 | .attr("orient", "auto") |
| 65 | .append("svg:path") |
| 66 | .attr("d", "M0,-4L8,0L0,4"); |
| 67 | |
| 68 | this.graphElement = this.svg.append("g"); |
| 69 | |
| 70 | this.panZoom = d3.zoom<SVGElement, any>() |
| 71 | .scaleExtent([0.2, 40]) |
| 72 | .on("zoom", () => { |
| 73 | if (d3.event.shiftKey) return false; |
| 74 | this.graphElement.attr("transform", d3.event.transform); |
| 75 | return true; |
| 76 | }) |
| 77 | .on("start", () => { |
| 78 | if (d3.event.shiftKey) return; |
| 79 | d3.select("body").style("cursor", "move"); |
| 80 | }) |
| 81 | .on("end", () => d3.select("body").style("cursor", "auto")); |
| 82 | |
| 83 | this.svg.call(this.panZoom).on("dblclick.zoom", null); |
| 84 | } |
| 85 | |
| 86 | public createViewElement(): HTMLDivElement { |
| 87 | const pane = document.createElement("div"); |