blob: 415a21e4351d42fd483deb25c19bfc1d400efd42 [file] [log] [blame]
Steven Burrows57e24e92016-08-04 18:38:24 +01001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Topology Links Module.
19 Module that holds the links for a region
20 */
21
22(function () {
23 'use strict';
24
Steven Burrows1c5c8612016-10-05 13:45:13 -050025 var $log, Collection, Model, ts, sus, t2zs, t2vs;
Steven Burrows9edc7e02016-08-29 11:52:07 +010026
27 var linkLabelOffset = '0.35em';
Steven Burrows57e24e92016-08-04 18:38:24 +010028
Steven Burrowsec1f45c2016-08-08 16:14:41 +010029 var widthRatio = 1.4,
30 linkScale = d3.scale.linear()
31 .domain([1, 12])
32 .range([widthRatio, 12 * widthRatio])
33 .clamp(true),
34 allLinkTypes = 'direct indirect optical tunnel UiDeviceLink',
35 allLinkSubTypes = 'inactive not-permitted';
36
37 // configuration
38 var linkConfig = {
39 light: {
40 baseColor: '#939598',
41 inColor: '#66f',
42 outColor: '#f00'
43 },
44 dark: {
45 // TODO : theme
46 baseColor: '#939598',
47 inColor: '#66f',
48 outColor: '#f00'
49 },
50 inWidth: 12,
51 outWidth: 10
52 };
53
Steven Burrowsec1f45c2016-08-08 16:14:41 +010054 function createLink() {
55
56 var linkPoints = this.linkEndPoints(this.get('epA'), this.get('epB'));
Steven Burrowsec1f45c2016-08-08 16:14:41 +010057
58 var attrs = angular.extend({}, linkPoints, {
59 key: this.get('id'),
60 class: 'link',
Steven Burrowsec1f45c2016-08-08 16:14:41 +010061 srcPort: this.get('srcPort'),
62 tgtPort: this.get('dstPort'),
63 position: {
64 x1: 0,
65 y1: 0,
66 x2: 0,
67 y2: 0
68 }
69 // functions to aggregate dual link state
Steven Burrows9edc7e02016-08-29 11:52:07 +010070 // extra: link.extra
Steven Burrowsec1f45c2016-08-08 16:14:41 +010071 });
72
73 this.set(attrs);
74 }
75
Steven Burrows9edc7e02016-08-29 11:52:07 +010076 function rectAroundText(el) {
77 var text = el.select('text'),
78 box = text.node().getBBox();
79
80 // translate the bbox so that it is centered on [x,y]
81 box.x = -box.width / 2;
82 box.y = -box.height / 2;
83
84 // add padding
85 box.x -= 4;
86 box.width += 8;
87 return box;
88 }
89
Steven Burrowsdfa52b02016-09-02 13:50:43 +010090 function isLinkOnline(node) {
91 return (node.get('nodeType') === 'region') ? true : node.get('online');
92 }
93
Steven Burrowsec1f45c2016-08-08 16:14:41 +010094 function linkEndPoints(srcId, dstId) {
95
Steven Burrowsdfa52b02016-09-02 13:50:43 +010096 var sourceNode = this.region.findNodeById(srcId);
97 var targetNode = this.region.findNodeById(dstId);
Steven Burrowsec1f45c2016-08-08 16:14:41 +010098
Steven Burrows6deb4ce2016-08-26 16:06:23 +010099 if (!sourceNode || !targetNode) {
100 $log.error('Node(s) not on map for link:' + srcId + ':' + dstId);
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100101 // logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100102 return null;
103 }
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100104
105 this.source = sourceNode.toJSON();
106 this.target = targetNode.toJSON();
107
108 return {
109 source: sourceNode,
110 target: targetNode
111 };
112 }
113
114 function createLinkCollection(data, _region) {
115
116 var LinkModel = Model.extend({
117 region: _region,
118 createLink: createLink,
119 linkEndPoints: linkEndPoints,
120 type: function () {
121 return this.get('type');
122 },
123 expected: function () {
Steven Burrows9edc7e02016-08-29 11:52:07 +0100124 // TODO: original code is: (s && s.expected) && (t && t.expected);
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100125 return true;
126 },
127 online: function () {
Steven Burrows9edc7e02016-08-29 11:52:07 +0100128
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100129 var source = this.get('source'),
130 target = this.get('target'),
131 sourceOnline = isLinkOnline(source),
132 targetOnline = isLinkOnline(target);
133
134 return (sourceOnline) && (targetOnline);
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100135 },
Steven Burrows9edc7e02016-08-29 11:52:07 +0100136 enhance: function () {
137 var data = [],
138 point;
139
140 angular.forEach(this.collection.models, function (link) {
141 link.unenhance();
142 });
143
144 this.el.classed('enhanced', true);
Steven Burrows9edc7e02016-08-29 11:52:07 +0100145
Steven Burrows1c5c8612016-10-05 13:45:13 -0500146 if (showPort()) {
147 point = this.locatePortLabel();
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100148 angular.extend(point, {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500149 id: 'topo-port-tgt',
150 num: this.get('portB')
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100151 });
152 data.push(point);
Steven Burrows1c5c8612016-10-05 13:45:13 -0500153
154 if (this.get('portA')) {
155 point = this.locatePortLabel(1);
156 angular.extend(point, {
157 id: 'topo-port-src',
158 num: this.get('portA')
159 });
160 data.push(point);
161 }
162
163 var entering = d3.select('#topo-portLabels')
164 .selectAll('.portLabel')
165 .data(data).enter().append('g')
166 .classed('portLabel', true)
167 .attr('id', function (d) { return d.id; });
168
169 entering.each(function (d) {
170 var el = d3.select(this),
171 rect = el.append('rect'),
172 text = el.append('text').text(d.num);
173
174 var rectSize = rectAroundText(el);
175
176 rect.attr(rectSize)
177 .attr('rx', 2)
178 .attr('ry', 2);
179
180 text.attr('dy', linkLabelOffset)
181 .attr('text-anchor', 'middle');
182
183 el.attr('transform', sus.translate(d.x, d.y));
184 });
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100185 }
Steven Burrows9edc7e02016-08-29 11:52:07 +0100186 },
187 unenhance: function () {
188 this.el.classed('enhanced', false);
189 d3.select('#topo-portLabels').selectAll('.portLabel').remove();
190 },
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100191 locatePortLabel: function (src) {
Steven Burrows9edc7e02016-08-29 11:52:07 +0100192 var offset = 32,
193 pos = this.get('position'),
194 nearX = src ? pos.x1 : pos.x2,
195 nearY = src ? pos.y1 : pos.y2,
196 farX = src ? pos.x2 : pos.x1,
197 farY = src ? pos.y2 : pos.y1;
198
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100199 function dist(x, y) {
200 return Math.sqrt(x * x + y * y);
201 }
Steven Burrows9edc7e02016-08-29 11:52:07 +0100202
203 var dx = farX - nearX,
204 dy = farY - nearY,
205 k = offset / dist(dx, dy);
206
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100207 return { x: k * dx + nearX, y: k * dy + nearY };
Steven Burrows9edc7e02016-08-29 11:52:07 +0100208 },
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100209 restyleLinkElement: function (immediate) {
210 // this fn's job is to look at raw links and decide what svg classes
211 // need to be applied to the line element in the DOM
212 var th = ts.theme(),
213 el = this.el,
214 type = this.get('type'),
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100215 online = this.online(),
216 modeCls = this.expected() ? 'inactive' : 'not-permitted',
217 delay = immediate ? 0 : 1000;
218
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100219 // NOTE: understand why el is sometimes undefined on addLink events...
220 // Investigated:
221 // el is undefined when it's a reverse link that is being added.
222 // updateLinks (which sets ldata.el) isn't called before this is called.
223 // Calling _updateLinks in addLinkUpdate fixes it, but there might be
224 // a more efficient way to fix it.
225 if (el && !el.empty()) {
226 el.classed('link', true);
227 el.classed(allLinkSubTypes, false);
228 el.classed(modeCls, !online);
229 el.classed(allLinkTypes, false);
230 if (type) {
231 el.classed(type, true);
232 }
233 el.transition()
234 .duration(delay)
Steven Burrows0616e802016-10-06 21:45:07 -0500235 .attr('stroke-width', linkScale(widthRatio))
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100236 .attr('stroke', linkConfig[th].baseColor);
237 }
238 },
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100239 onEnter: function (el) {
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100240 var link = d3.select(el);
Steven Burrows9edc7e02016-08-29 11:52:07 +0100241
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100242 this.el = link;
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100243 this.restyleLinkElement();
244
245 if (this.get('type') === 'hostLink') {
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100246 // sus.visible(link, api.showHosts());
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100247 }
Steven Burrows0616e802016-10-06 21:45:07 -0500248 },
249 setScale: function () {
250 var width = linkScale(widthRatio / t2zs.scale());
251 this.el.style('stroke-width', width + 'px');
Steven Burrows1c5c8612016-10-05 13:45:13 -0500252 },
253 update: function () {
254 if (this.el.classed('enhanced')) {
255 this.enhance();
256 }
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100257 }
258 });
Steven Burrows57e24e92016-08-04 18:38:24 +0100259
260 var LinkCollection = Collection.extend({
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100261 model: LinkModel
Steven Burrows57e24e92016-08-04 18:38:24 +0100262 });
263
264 return new LinkCollection(data);
265 }
266
Steven Burrows1c5c8612016-10-05 13:45:13 -0500267 function showPort() {
268 return t2vs.getPortHighlighting();
269 }
270
Steven Burrows57e24e92016-08-04 18:38:24 +0100271 angular.module('ovTopo2')
272 .factory('Topo2LinkService',
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100273 ['$log', 'Topo2Collection', 'Topo2Model',
Steven Burrows0616e802016-10-06 21:45:07 -0500274 'ThemeService', 'SvgUtilService', 'Topo2ZoomService',
Steven Burrows1c5c8612016-10-05 13:45:13 -0500275 'Topo2ViewService',
276 function (_$log_, _Collection_, _Model_, _ts_, _sus_,
277 _t2zs_, _t2vs_) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100278
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100279 $log = _$log_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100280 ts = _ts_;
Steven Burrows9edc7e02016-08-29 11:52:07 +0100281 sus = _sus_;
Steven Burrows0616e802016-10-06 21:45:07 -0500282 t2zs = _t2zs_;
Steven Burrows1c5c8612016-10-05 13:45:13 -0500283 t2vs = _t2vs_;
Steven Burrows57e24e92016-08-04 18:38:24 +0100284 Collection = _Collection_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100285 Model = _Model_;
Steven Burrows57e24e92016-08-04 18:38:24 +0100286
287 return {
288 createLinkCollection: createLinkCollection
289 };
290 }
291 ]);
292
293})();