blob: 9d464943965aab7c8c8da72b3dc0fcb5c2fc8a23 [file] [log] [blame]
Steven Burrowsec1f45c2016-08-08 16:14:41 +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/*
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 Burrows1c5c8612016-10-05 13:45:13 -050025 var ps, 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 = {
36 light: {
37 online: '#444444',
38 offline: '#cccccc'
39 },
40 dark: {
41 // TODO: theme
42 online: '#444444',
43 offline: '#cccccc'
44 }
45 };
46
Steven Burrowsec1f45c2016-08-08 16:14:41 +010047 angular.module('ovTopo2')
Steven Burrowsaf96a212016-12-28 12:57:02 +000048 .factory('Topo2NodeModel', [
49 'Topo2Model', 'FnService', 'Topo2PrefsService',
Steven Burrows482d9502016-09-27 11:24:58 -070050 'SvgUtilService', 'IconService', 'ThemeService',
Steven Burrows1c5c8612016-10-05 13:45:13 -050051 'Topo2MapConfigService', 'Topo2ZoomService', 'Topo2NodePositionService',
52 function (Model, _fn_, _ps_, _sus_, _is_, _ts_,
53 _t2mcs_, zoomService, _t2nps_) {
Steven Burrowsec1f45c2016-08-08 16:14:41 +010054
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070055 ts = _ts_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +010056 fn = _fn_;
Steven Burrows37549ee2016-09-21 14:41:39 +010057 ps = _ps_;
Steven Burrowsbbe3dda2016-09-26 14:41:59 -070058 sus = _sus_;
59 is = _is_;
Steven Burrowse7cc3082016-09-27 11:24:58 -070060 t2mcs = _t2mcs_;
Steven Burrows1c5c8612016-10-05 13:45:13 -050061 t2nps = _t2nps_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +010062
63 return Model.extend({
64 initialize: function () {
65 this.node = this.createNode();
Steven Burrows1c5c8612016-10-05 13:45:13 -050066 this._events = {
67 'mouseover': 'mouseoverHandler',
68 'mouseout': 'mouseoutHandler'
69 };
Steven Burrowsec1f45c2016-08-08 16:14:41 +010070 },
Steven Burrows86af4352016-11-16 18:19:12 -060071 select: function () {
72 var ev = d3.event;
73
74 // TODO: if single selection clear selected devices, hosts, sub-regions
75
76 if (ev.shiftKey) {
77 // TODO: Multi-Select Details Panel
78 this.set('selected', true);
79 } else {
80
81 var s = Boolean(this.get('selected'));
82 // Clear all selected Items
83 _.each(this.collection.models, function (m) {
84 m.set('selected', false);
85 });
86
87 this.set('selected', !s);
88 }
89
90 var selected = this.collection.filter(function (m) {
91 return m.get('selected');
92 });
93
94 return selected;
95 },
Steven Burrows68d6f952017-03-10 13:53:35 +000096 index: function () {
97
98 var models = this.collection.models,
99 id = this.get('id');
100
101 var index = _.find(models, function (model, i) {
102 return model.get('id') === id;
103 });
104
105 return index || models.length;
106 },
Steven Burrows1aa4f582016-12-13 15:05:41 -0500107 deselect: function () {
108 this.set('selected', false);
109 },
Steven Burrowse7cc3082016-09-27 11:24:58 -0700110 createNode: function () {
Steven Burrowse7cc3082016-09-27 11:24:58 -0700111 this.set('svgClass', this.svgClassName());
Steven Burrows1c5c8612016-10-05 13:45:13 -0500112 t2nps.positionNode(this);
Steven Burrowse7cc3082016-09-27 11:24:58 -0700113 return this;
114 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700115 setUpEvents: function () {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500116 var _this = this,
117 events = angular.extend({}, this._events, this.events);
118 angular.forEach(events, function (handler, key) {
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700119 _this.el.on(key, _this[handler].bind(_this));
120 });
121 },
Steven Burrows1c5c8612016-10-05 13:45:13 -0500122 mouseoverHandler: function () {
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000123 this.set('hovered', true);
Steven Burrows1c5c8612016-10-05 13:45:13 -0500124 },
125 mouseoutHandler: function () {
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000126 this.set('hovered', false);
127 },
128 fix: function (fixed) {
129 this.set({ fixed: fixed });
130 this.fixed = fixed;
Steven Burrows1c5c8612016-10-05 13:45:13 -0500131 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700132 icon: function () {
133 return 'unknown';
134 },
Steven Burrows583f4be2016-11-04 14:06:50 +0100135 labelIndex: function () {
136 return ps.get('dlbls');
137 },
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100138 label: function () {
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100139 var props = this.get('props'),
140 id = this.get('id'),
Steven Burrows1c5c8612016-10-05 13:45:13 -0500141 friendlyName = props && props.name ? props.name : id,
142 labels = ['', friendlyName || id, id],
Steven Burrows583f4be2016-11-04 14:06:50 +0100143 nli = this.labelIndex(),
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100144 idx = (nli < labels.length) ? nli : 0;
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100145
146 return labels[idx];
147 },
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100148 trimLabel: function (label) {
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100149 return (label && label.trim()) || '';
150 },
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100151 computeLabelWidth: function (el) {
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100152 var text = el.select('text'),
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100153 box = text.node().getBBox();
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100154 return box.width + labelPad * 2;
155 },
Steven Burrows42eb9e22017-02-06 14:20:24 +0000156 devGlyphColor: function () {
157 var o = this.get('online'),
158 id = this.get('master'),
159 otag = o ? 'online' : 'offline';
160 return o ? sus.cat7().getColor(id, 0, ts.theme()) :
161 dColTheme[ts.theme()][otag];
162 },
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100163 addLabelElements: function (label) {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500164 var rect = this.el.append('rect')
165 .attr('class', 'node-container');
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700166 var glythRect = this.el.append('rect')
Steven Burrows42eb9e22017-02-06 14:20:24 +0000167 .attr('class', 'icon-rect')
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700168 .attr('y', -halfDevIcon)
169 .attr('x', -halfDevIcon)
170 .attr('width', devIconDim)
171 .attr('height', devIconDim)
Steven Burrows42eb9e22017-02-06 14:20:24 +0000172 .style('fill', this.devGlyphColor.bind(this));
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700173
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100174 var text = this.el.append('text').text(label)
175 .attr('text-anchor', 'left')
176 .attr('y', '0.3em')
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700177 .attr('x', halfDevIcon + labelPad + textPad);
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100178
179 return {
180 rect: rect,
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700181 glythRect: glythRect,
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100182 text: text
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100183 };
Steven Burrows6deb4ce2016-08-26 16:06:23 +0100184 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700185 labelBox: function (dim, labelWidth) {
186 var _textPad = (textPad * 2) - labelPad;
187
188 if (labelWidth === 0) {
189 _textPad = 0;
190 }
191
192 return {
193 x: -dim / 2 - labelPad,
194 y: -dim / 2 - labelPad,
195 width: dim + labelWidth + (labelPad * 2) + _textPad,
196 height: dim + (labelPad * 2)
197 };
198 },
199 iconBox: function (dim, labelWidth) {
Steven Burrows37549ee2016-09-21 14:41:39 +0100200 return {
201 x: -dim / 2,
202 y: -dim / 2,
203 width: dim + labelWidth,
204 height: dim
205 };
206 },
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100207 svgClassName: function () {
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100208 return fn.classNames('node',
209 this.nodeType,
210 this.get('type'),
211 {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500212 online: this.get('online'),
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000213 selected: this.get('selected'),
214 hovered: this.get('hovered'),
215 fixed: this.get('fixed')
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100216 }
217 );
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100218 },
Steven Burrowse7cc3082016-09-27 11:24:58 -0700219 lngLatFromCoord: function (coord) {
220 var p = t2mcs.projection();
221 return p ? p.invert(coord) : [0, 0];
222 },
Steven Burrows1c5c8612016-10-05 13:45:13 -0500223 resetPosition: function () {
224 t2nps.setLongLat(this);
225 },
Steven Burrows37549ee2016-09-21 14:41:39 +0100226 update: function () {
227 this.updateLabel();
228 },
229 updateLabel: function () {
230 var node = this.el,
231 label = this.trimLabel(this.label()),
232 labelWidth;
233
234 node.select('text').text(label);
235 labelWidth = label ? this.computeLabelWidth(node) : 0;
236
237 node.select('rect')
238 .transition()
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700239 .attr(this.labelBox(devIconDim, labelWidth));
Steven Burrows37549ee2016-09-21 14:41:39 +0100240 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700241 onEnter: function (el) {
242 this.el = d3.select(el);
243 this.render();
244 },
Steven Burrows0616e802016-10-06 21:45:07 -0500245 setScale: function () {
246
247 var dim = devIconDim,
248 multipler = 1;
249
250 if (dim * zoomService.scale() < devIconDimMin) {
251 multipler = devIconDimMin / (dim * zoomService.scale());
252 } else if (dim * zoomService.scale() > devIconDimMax) {
253 multipler = devIconDimMax / (dim * zoomService.scale());
254 }
255
Steven Burrows1c5c8612016-10-05 13:45:13 -0500256 this.el.selectAll('*')
257 .style('transform', 'scale(' + multipler + ')');
Steven Burrows0616e802016-10-06 21:45:07 -0500258 },
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700259 render: function () {
260 var node = this.el,
261 glyphId = this.icon(this.get('type')),
262 label = this.trimLabel(this.label()),
263 glyph, labelWidth;
264
265 // Label
266 var labelElements = this.addLabelElements(label);
267 labelWidth = label ? this.computeLabelWidth(node) : 0;
Steven Burrows1c5c8612016-10-05 13:45:13 -0500268 labelElements.rect
269 .attr(this.labelBox(devIconDim, labelWidth));
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700270
271 // Icon
272 glyph = is.addDeviceIcon(node, glyphId, devIconDim);
273 glyph.attr(this.iconBox(devIconDim, 0));
274 glyph.style('fill', 'white');
275
Steven Burrows583f4be2016-11-04 14:06:50 +0100276 node.attr('transform',
277 sus.translate(-halfDevIcon, -halfDevIcon));
Steven Burrowsbbe3dda2016-09-26 14:41:59 -0700278
279 if (this.events) {
280 this.setUpEvents();
281 }
Steven Burrows0616e802016-10-06 21:45:07 -0500282
283 this.setScale();
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100284 }
285 });
286 }]
287 );
288})();