|
1 | 1 | class Link { |
2 | | - constructor(eventId, trigger, args) { |
| 2 | + constructor(eventId, trigger, args, reltype) { |
3 | 3 | this.eventId = eventId; |
4 | 4 | this.trigger = trigger; |
5 | 5 | this.arguments = args; |
6 | 6 | this.links = []; |
7 | | - console.log('trigger\t\t', this.val); |
8 | | - console.log.apply(null, args); |
| 7 | + this.reltype = reltype; |
| 8 | + // console.log('trigger\t\t', this.val); |
| 9 | + // console.log.apply(null, args); |
| 10 | + |
| 11 | + if (this.trigger) { this.trigger.links.push(this); } |
| 12 | + this.arguments.forEach(arg => arg.anchor.links.push(this)); |
9 | 13 |
|
10 | 14 | this.mainSVG = null; |
11 | 15 | this.svg = null; |
12 | 16 | this.handles = []; |
13 | | - this.lines = []; |
| 17 | + this.line = null; |
14 | 18 | this.svgTexts = []; |
15 | 19 | } |
16 | 20 |
|
17 | 21 | init(svg) { |
18 | | - // this.mainSVG = svg; |
19 | | - // this.svg = svg.group().addClass('link'); |
20 | | - // if (this.trigger) { |
21 | | - // console.log(this.trigger.x, this.trigger.boxWidth, this.trigger.row); |
22 | | - // } |
23 | | - } |
24 | | - |
25 | | - /** |
26 | | - * remove reference to a link |
27 | | - * @return array containing the link, or undefined |
28 | | - */ |
29 | | - detachLink(link) { |
30 | | - let i = this.links.indexOf(link); |
31 | | - if (i > -1) { |
32 | | - return this.links.splice(i, 1); |
| 22 | + this.mainSVG = svg; |
| 23 | + this.svg = svg.group().addClass('link'); |
| 24 | + |
| 25 | + // init handles |
| 26 | + const s = 4; |
| 27 | + if (this.trigger) { |
| 28 | + // draw a diamond at the location of the trigger |
| 29 | + let x = this.trigger.cx; |
| 30 | + let y = this.trigger.absoluteY; |
| 31 | + let handle = this.svg.path(`M${s},0L0,${s}L${-s},0L0,${-s}Z`) |
| 32 | + .x(x - s) |
| 33 | + .y(y); |
| 34 | + this.handles.push({ anchor: this.trigger, handle, x, y }); |
| 35 | + } |
| 36 | + this.arguments.forEach(arg => { |
| 37 | + // draw a triangle at the location of the argument |
| 38 | + let x = arg.anchor.cx; |
| 39 | + let y = arg.anchor.absoluteY; |
| 40 | + |
| 41 | + let handle = this.svg.path(`M${[s, -s/2]}L${[-s, -s/2]}L0,${s}`) |
| 42 | + .x(x - s) |
| 43 | + .y(y); |
| 44 | + this.handles.push({ anchor: arg.anchor, handle, x, y }); |
| 45 | + |
| 46 | + if (this.trigger) { |
| 47 | + let text = this.svg.text(arg.type) |
| 48 | + .y(-7) |
| 49 | + .addClass('link-text'); |
| 50 | + this.svgTexts.push(text); |
| 51 | + } |
| 52 | + }); |
| 53 | + if (this.reltype) { |
| 54 | + let text = this.svg.text(this.reltype) |
| 55 | + .y(-7) |
| 56 | + .addClass('link-text'); |
| 57 | + this.svgTexts.push(text); |
33 | 58 | } |
| 59 | + |
| 60 | + this.line = this.svg.path() |
| 61 | + .addClass('polyline'); |
| 62 | + this.draw(); |
| 63 | + |
| 64 | + //TODO: sort links and offset according to # of links the anchor has |
| 65 | + } |
| 66 | + |
| 67 | + draw(anchor) { |
| 68 | + const s = 4; |
| 69 | + this.handles.forEach(h => { |
| 70 | + if (anchor === h.anchor) { |
| 71 | + h.x = anchor.cx; |
| 72 | + h.y = anchor.absoluteY; |
| 73 | + h.handle |
| 74 | + .x(h.x - s) |
| 75 | + .y(h.y); |
| 76 | + } |
| 77 | + }) |
| 78 | + if (this.line) { |
| 79 | + let d; |
| 80 | + if (this.trigger) { |
| 81 | + d = this.arguments.map((arg, i) => { |
| 82 | + let tx = this.trigger.cx |
| 83 | + , ty = this.trigger.absoluteY |
| 84 | + , ax = arg.anchor.cx |
| 85 | + , ay = arg.anchor.absoluteY; |
| 86 | + |
| 87 | + let dx = (tx < ax) ? 10 : -10; |
| 88 | + let dy = ty - ay; // FIXME: this only handles case for trigger.y on lower level than arg.y |
| 89 | + |
| 90 | + // get text position |
| 91 | + let len = this.svgTexts[i] |
| 92 | + .x((ax + tx) / 2) |
| 93 | + .y(arg.anchor.absoluteY - 10 - 7) |
| 94 | + .length() / 2; |
| 95 | + |
| 96 | + let cx = (ax - tx) / 2 - dx; |
| 97 | + if (cx < 0) { len = -len; } |
| 98 | + |
| 99 | + // get path string |
| 100 | + return 'M' + [tx, ty] |
| 101 | + + 'c' + [0, -10 - dy, 0, -10 - dy, dx, -10 - dy] |
| 102 | + + 'l' + [cx - len, 0] |
| 103 | + + 'm' + [len * 2, 0] |
| 104 | + + 'l' + [cx - len, 0] |
| 105 | + + 'c' + [dx, 0, dx, 10, dx, 10]; |
| 106 | + }).join(); |
| 107 | + } |
| 108 | + else { |
| 109 | + let avg = this.arguments.reduce((acc, a) => acc + a.anchor.cx, 0) / this.arguments.length; |
| 110 | + this.svgTexts[0].x(avg) |
| 111 | + .y(this.arguments[0].anchor.absoluteY - 10 - 7); |
| 112 | + d = 'M' + [this.arguments[0].anchor.cx, this.arguments[0].anchor.absoluteY] |
| 113 | + + 'L' + [this.arguments[1].anchor.cx, this.arguments[1].anchor.absoluteY]; |
| 114 | + } |
| 115 | + this.line.plot(d); |
| 116 | + } |
| 117 | + |
| 118 | + this.links.forEach(l => l.draw(this)); |
34 | 119 | } |
35 | 120 |
|
36 | 121 | remove() { |
37 | 122 | this.svg.remove(); |
38 | 123 |
|
| 124 | + let self = this; |
| 125 | + // remove reference to a link |
| 126 | + function detachLink(anchor) { |
| 127 | + let i = anchor.links.indexOf(self); |
| 128 | + if (i > -1) { |
| 129 | + anchor.links.splice(i, 1); |
| 130 | + } |
| 131 | + }; |
| 132 | + |
39 | 133 | // remove references to link from all anchors |
40 | | - if (this.trigger) { this.trigger.detachLink(this); } |
41 | | - this.arguments.forEach(arg => arg.detachLink(this)); |
| 134 | + if (this.trigger) { detachLink(this.trigger); } |
| 135 | + this.arguments.forEach(arg => detachLink(arg.anchor)); |
42 | 136 | } |
43 | 137 |
|
44 | 138 | hasAnchor(a) { |
45 | 139 | if (this.trigger && a === this.trigger) { return true; } |
46 | 140 | return this.arguments.find(arg => arg.anchor === a); |
47 | 141 | } |
48 | 142 |
|
| 143 | + get cx() { |
| 144 | + if (this.trigger) { |
| 145 | + // if (this.trigger.links.length > 1) { |
| 146 | + // let offset = this.trigger.links.indexOf(this) / (this.trigger.links.length - 1) - 0.5; |
| 147 | + // return this.trigger.cx + offset * 200; |
| 148 | + // } |
| 149 | + return this.trigger.cx; |
| 150 | + } |
| 151 | + if (this.arguments.length > 0) { |
| 152 | + return this.arguments.reduce((acc, arg) => acc + arg.cx, 0) / this.arguments.length; |
| 153 | + } |
| 154 | + return 0; |
| 155 | + } |
| 156 | + get absoluteY() { |
| 157 | + if (this.trigger) { return this.trigger.absoluteY - 15; } |
| 158 | + if (this.arguments[0]) { return this.arguments[0].absoluteY - 15; } |
| 159 | + return 0; |
| 160 | + } |
| 161 | + |
49 | 162 | get val() { |
50 | 163 | return this.trigger && this.trigger.val; |
51 | 164 | } |
|
0 commit comments