blob: fd9c55b77f0dff08c944b5574cb0164552cfb4ed [file] [log] [blame]
Steven Burrowsec1f45c2016-08-08 16:14:41 +01001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Steven Burrowsec1f45c2016-08-08 16:14:41 +01003 *
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/*
Steven Burrows1c5c8612016-10-05 13:45:13 -050018 ONOS GUI -- Topology Node Module.
19 Module that contains model for nodes within the topology
Steven Burrowsec1f45c2016-08-08 16:14:41 +010020 */
21
22(function () {
23 'use strict';
24
Steven Burrows02e67f42017-04-13 13:59:43 -070025 var t2ps, sus, is, ts, t2mcs, t2nps, fn;
Steven Burrowsec1f45c2016-08-08 16:14:41 +010026
Steven Burrows6deb4ce2016-08-26 16:06:23 +010027 var devIconDim = 36,
Steven Burrows0616e802016-10-06 21:45:07 -050028 devIconDimMin = 20,
29 devIconDimMax = 40,
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070030 labelPad = 5,
31 textPad = 5,
32 halfDevIcon = devIconDim / 2;
33
34 // note: these are the device icon colors without affinity (no master)
35 var dColTheme = {
Simon Huntb3656d42017-04-07 18:15:35 -070036 light: {
37 online: '#444444',
Steven Burrows1c2a9682017-07-14 16:52:46 +010038 offline: '#cccccc',
Simon Huntb3656d42017-04-07 18:15:35 -070039 },
40 dark: {
41 // TODO: theme
42 online: '#444444',
Steven Burrows1c2a9682017-07-14 16:52:46 +010043 offline: '#cccccc',
44 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070045 },
Simon Huntb3656d42017-04-07 18:15:35 -070046 // and here are the stroke colors of the glyph, per theme
47 dUseTheme = {
48 light: 'white',
Steven Burrows1c2a9682017-07-14 16:52:46 +010049 dark: 'black',
Simon Huntb3656d42017-04-07 18:15:35 -070050 };
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070051
Steven Burrowsec1f45c2016-08-08 16:14:41 +010052 angular.module('ovTopo2')
Steven Burrowsaf96a212016-12-28 12:57:02 +000053 .factory('Topo2NodeModel', [
54 'Topo2Model', 'FnService', 'Topo2PrefsService',
Steven Burrows482d9502016-09-27 11:24:58 -070055 'SvgUtilService', 'IconService', 'ThemeService',
Steven Burrows1c5c8612016-10-05 13:45:13 -050056 'Topo2MapConfigService', 'Topo2ZoomService', 'Topo2NodePositionService',
Steven Burrowsc515e602017-04-13 11:17:40 -070057 'Topo2SelectService', 'Topo2MastershipService',
Steven Burrows448468c2017-04-13 16:09:30 -070058 function (Model, _fn_, _t2ps_, _sus_, _is_, _ts_,
Steven Burrowsc515e602017-04-13 11:17:40 -070059 _t2mcs_, zoomService, _t2nps_, t2ss, t2mss) {
Steven Burrowsec1f45c2016-08-08 16:14:41 +010060
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070061 ts = _ts_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +010062 fn = _fn_;
Steven Burrows02e67f42017-04-13 13:59:43 -070063 t2ps = _t2ps_;
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070064 sus = _sus_;
65 is = _is_;
Steven Burrowse7cc3082016-09-27 11:24:58 -070066 t2mcs = _t2mcs_;
Steven Burrows1c5c8612016-10-05 13:45:13 -050067 t2nps = _t2nps_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +010068
69 return Model.extend({
70 initialize: function () {
71 this.node = this.createNode();
Steven Burrowsc515e602017-04-13 11:17:40 -070072 this.mastershipService = t2mss;
Steven Burrows1c5c8612016-10-05 13:45:13 -050073 this._events = {
74 'mouseover': 'mouseoverHandler',
Steven Burrows1c2a9682017-07-14 16:52:46 +010075 'mouseout': 'mouseoutHandler',
Steven Burrows1c5c8612016-10-05 13:45:13 -050076 };
Steven Burrowsec1f45c2016-08-08 16:14:41 +010077 },
Steven Burrows86af4352016-11-16 18:19:12 -060078 select: function () {
Steven Burrows5fa057e2017-03-15 17:07:56 +000079 this.set('selected', true);
Steven Burrows86af4352016-11-16 18:19:12 -060080 },
Steven Burrows68d6f952017-03-10 13:53:35 +000081 index: function () {
82
83 var models = this.collection.models,
84 id = this.get('id');
85
86 var index = _.find(models, function (model, i) {
87 return model.get('id') === id;
88 });
89
90 return index || models.length;
91 },
Steven Burrows1aa4f582016-12-13 15:05:41 -050092 deselect: function () {
93 this.set('selected', false);
94 },
Steven Burrowse7cc3082016-09-27 11:24:58 -070095 createNode: function () {
Steven Burrowse7cc3082016-09-27 11:24:58 -070096 this.set('svgClass', this.svgClassName());
Steven Burrows1c5c8612016-10-05 13:45:13 -050097 t2nps.positionNode(this);
Steven Burrowse7cc3082016-09-27 11:24:58 -070098 return this;
99 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700100 setUpEvents: function () {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500101 var _this = this,
102 events = angular.extend({}, this._events, this.events);
103 angular.forEach(events, function (handler, key) {
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700104 _this.el.on(key, _this[handler].bind(_this));
105 });
106 },
Steven Burrows1c5c8612016-10-05 13:45:13 -0500107 mouseoverHandler: function () {
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000108 this.set('hovered', true);
Steven Burrows1c5c8612016-10-05 13:45:13 -0500109 },
110 mouseoutHandler: function () {
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000111 this.set('hovered', false);
112 },
Steven Burrows5fa057e2017-03-15 17:07:56 +0000113 onClick: function () {
114 if (d3.event.defaultPrevented) return;
115
116 d3.event.preventDefault();
117 t2ss.selectObject(this, this.multiSelectEnabled);
118 },
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000119 fix: function (fixed) {
120 this.set({ fixed: fixed });
121 this.fixed = fixed;
Steven Burrows1c5c8612016-10-05 13:45:13 -0500122 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700123 icon: function () {
124 return 'unknown';
125 },
Steven Burrows583f4be2016-11-04 14:06:50 +0100126 labelIndex: function () {
Steven Burrows02e67f42017-04-13 13:59:43 -0700127 return t2ps.get('dlbls');
Steven Burrows583f4be2016-11-04 14:06:50 +0100128 },
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100129 label: function () {
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100130 var props = this.get('props'),
131 id = this.get('id'),
Steven Burrows1c5c8612016-10-05 13:45:13 -0500132 friendlyName = props && props.name ? props.name : id,
133 labels = ['', friendlyName || id, id],
Steven Burrows583f4be2016-11-04 14:06:50 +0100134 nli = this.labelIndex(),
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100135 idx = (nli < labels.length) ? nli : 0;
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100136
137 return labels[idx];
138 },
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100139 trimLabel: function (label) {
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100140 return (label && label.trim()) || '';
141 },
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100142 computeLabelWidth: function (el) {
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100143 var text = el.select('text'),
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100144 box = text.node().getBBox();
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100145 return box.width + labelPad * 2;
146 },
Steven Burrows42eb9e22017-02-06 14:20:24 +0000147 devGlyphColor: function () {
148 var o = this.get('online'),
149 id = this.get('master'),
150 otag = o ? 'online' : 'offline';
151 return o ? sus.cat7().getColor(id, 0, ts.theme()) :
152 dColTheme[ts.theme()][otag];
153 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700154 labelBox: function (dim, labelWidth) {
155 var _textPad = (textPad * 2) - labelPad;
156
157 if (labelWidth === 0) {
158 _textPad = 0;
159 }
160
161 return {
162 x: -dim / 2 - labelPad,
163 y: -dim / 2 - labelPad,
164 width: dim + labelWidth + (labelPad * 2) + _textPad,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100165 height: dim + (labelPad * 2),
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700166 };
167 },
168 iconBox: function (dim, labelWidth) {
Steven Burrows37549ee2016-09-21 14:41:39 +0100169 return {
170 x: -dim / 2,
171 y: -dim / 2,
172 width: dim + labelWidth,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100173 height: dim,
Steven Burrows37549ee2016-09-21 14:41:39 +0100174 };
175 },
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100176 svgClassName: function () {
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100177 return fn.classNames('node',
178 this.nodeType,
179 this.get('type'),
180 {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500181 online: this.get('online'),
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000182 selected: this.get('selected'),
183 hovered: this.get('hovered'),
Steven Burrowsc515e602017-04-13 11:17:40 -0700184 fixed: this.get('fixed'),
Steven Burrows1c2a9682017-07-14 16:52:46 +0100185 suppressedmax: this.get('mastership'),
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100186 }
187 );
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100188 },
Steven Burrowse7cc3082016-09-27 11:24:58 -0700189 lngLatFromCoord: function (coord) {
190 var p = t2mcs.projection();
191 return p ? p.invert(coord) : [0, 0];
192 },
Steven Burrows1c5c8612016-10-05 13:45:13 -0500193 resetPosition: function () {
194 t2nps.setLongLat(this);
195 },
Steven Burrowsc515e602017-04-13 11:17:40 -0700196 displayMastership: function () {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100197 this.set({ mastership: t2mss.mastership() !== null });
Steven Burrowsc515e602017-04-13 11:17:40 -0700198 },
Steven Burrows37549ee2016-09-21 14:41:39 +0100199 update: function () {
200 this.updateLabel();
201 },
202 updateLabel: function () {
203 var node = this.el,
204 label = this.trimLabel(this.label()),
205 labelWidth;
206
207 node.select('text').text(label);
208 labelWidth = label ? this.computeLabelWidth(node) : 0;
209
210 node.select('rect')
211 .transition()
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700212 .attr(this.labelBox(devIconDim, labelWidth));
Steven Burrows37549ee2016-09-21 14:41:39 +0100213 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700214 onEnter: function (el) {
215 this.el = d3.select(el);
216 this.render();
Steven Burrows8ba9e6d2017-11-01 16:01:23 +0000217
218 if (this.setOfflineVisibility) {
219 this.setOfflineVisibility();
220 }
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700221 },
Steven Burrows0616e802016-10-06 21:45:07 -0500222 setScale: function () {
223
Steven Burrowse8a455a2017-03-16 16:58:59 +0000224 if (!this.el) return;
225
Steven Burrows0616e802016-10-06 21:45:07 -0500226 var dim = devIconDim,
227 multipler = 1;
228
229 if (dim * zoomService.scale() < devIconDimMin) {
230 multipler = devIconDimMin / (dim * zoomService.scale());
231 } else if (dim * zoomService.scale() > devIconDimMax) {
232 multipler = devIconDimMax / (dim * zoomService.scale());
233 }
234
Steven Burrowsc64d1b22017-04-17 18:37:35 -0400235 this.el.select('.node-content')
Steven Burrows1c5c8612016-10-05 13:45:13 -0500236 .style('transform', 'scale(' + multipler + ')');
Steven Burrows0616e802016-10-06 21:45:07 -0500237 },
Steven Burrowsc64d1b22017-04-17 18:37:35 -0400238 addLabelElements: function (label) {
239
240 var labelG = this.el.select('.node-content')
241 .append('g')
242 .attr('class', 'label');
243
244 var rect = labelG.append('rect')
245 .attr('class', 'node-container');
246
247 var text = labelG.append('text').text(label)
248 .attr('text-anchor', 'left')
249 .attr('y', '0.3em')
250 .attr('x', halfDevIcon + labelPad + textPad);
251
252 return {
253 rect: rect,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100254 text: text,
Steven Burrowsc64d1b22017-04-17 18:37:35 -0400255 };
256 },
257 addIconElements: function (el) {
258
259 var glyphId = this.icon(this.get('type')),
260 glyph;
261
262 var iconG = el.append('g')
Steven Burrows1c2a9682017-07-14 16:52:46 +0100263 .attr('class', 'icon');
Steven Burrowsc64d1b22017-04-17 18:37:35 -0400264
265 iconG.append('rect')
266 .attr('class', 'icon-rect')
267 .attr('y', -halfDevIcon)
268 .attr('x', -halfDevIcon)
269 .attr('width', devIconDim)
270 .attr('height', devIconDim)
271 .style('fill', this.devGlyphColor.bind(this));
272
273 // Icon
274 glyph = is.addDeviceIcon(iconG, glyphId, devIconDim);
275 glyph.attr(this.iconBox(devIconDim, 0));
276 glyph.style('fill', dUseTheme[ts.theme()]);
277 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700278 render: function () {
279 var node = this.el,
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700280 label = this.trimLabel(this.label()),
Steven Burrowsc64d1b22017-04-17 18:37:35 -0400281 labelWidth;
282
283 var nodeG = node.append('g')
284 .attr('class', 'node-content');
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700285
286 // Label
287 var labelElements = this.addLabelElements(label);
288 labelWidth = label ? this.computeLabelWidth(node) : 0;
Steven Burrows1c5c8612016-10-05 13:45:13 -0500289 labelElements.rect
290 .attr(this.labelBox(devIconDim, labelWidth));
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700291
Steven Burrowsc64d1b22017-04-17 18:37:35 -0400292 this.addIconElements(nodeG);
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700293
Steven Burrows583f4be2016-11-04 14:06:50 +0100294 node.attr('transform',
295 sus.translate(-halfDevIcon, -halfDevIcon));
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700296
297 if (this.events) {
298 this.setUpEvents();
299 }
Steven Burrows0616e802016-10-06 21:45:07 -0500300
301 this.setScale();
Steven Burrows02e67f42017-04-13 13:59:43 -0700302 },
303
304 // Override Methods
305 setOfflineVisibility: function () {},
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100306 });
307 }]
308 );
309})();