blob: 481b96b66c4d98bc18380042c6ae692cce1341b2 [file] [log] [blame]
Simon Huntd5b96732016-07-08 13:22:27 -07001/*
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 Force Module.
19 Visualization of the topology in an SVG layer, using a D3 Force Layout.
20 */
21
22(function () {
23 'use strict';
24
25 // injected refs
Steven Burrows57e24e92016-08-04 18:38:24 +010026 var $log,
27 wss;
28
29 // SVG elements;
30 var linkG,
31 linkLabelG,
32 numLinkLblsG,
33 portLabelG,
34 nodeG;
35
36 // internal state
37 var settings, // merged default settings and options
38 force, // force layout object
39 drag, // drag behavior handler
40 network = {
41 nodes: [],
42 links: [],
43 linksByDevice: {},
44 lookup: {},
45 revLinkToKey: {}
46 },
47 lu, // shorthand for lookup
48 rlk, // shorthand for revLinktoKey
49 showHosts = false, // whether hosts are displayed
50 showOffline = true, // whether offline devices are displayed
51 nodeLock = false, // whether nodes can be dragged or not (locked)
52 fTimer, // timer for delayed force layout
53 fNodesTimer, // timer for delayed nodes update
54 fLinksTimer, // timer for delayed links update
55 dim, // the dimensions of the force layout [w,h]
56 linkNums = []; // array of link number labels
57
58 // D3 selections;
59 var link,
60 linkLabel,
61 node;
62
63 var $log, wss, t2is, t2rs;
Simon Huntd5b96732016-07-08 13:22:27 -070064
65 // ========================== Helper Functions
66
Steven Burrows57e24e92016-08-04 18:38:24 +010067 function init(_svg_, forceG, _uplink_, _dim_, opts) {
68
Simon Huntd5b96732016-07-08 13:22:27 -070069 $log.debug('Initialize topo force layout');
Steven Burrows57e24e92016-08-04 18:38:24 +010070
71 nodeG = forceG.append('g').attr('id', 'topo-nodes');
72 node = nodeG.selectAll('.node');
73
74 linkG = forceG.append('g').attr('id', 'topo-links');
75 linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels');
76 numLinkLblsG = forceG.append('g').attr('id', 'topo-numLinkLabels');
77 nodeG = forceG.append('g').attr('id', 'topo-nodes');
78 portLabelG = forceG.append('g').attr('id', 'topo-portLabels');
79
80 link = linkG.selectAll('.link');
81 linkLabel = linkLabelG.selectAll('.linkLabel');
82 node = nodeG.selectAll('.node');
83
84 var width = 640,
85 height = 480;
86
87 var nodes = [
88 { x: width/3, y: height/2 },
89 { x: 2*width/3, y: height/2 }
90 ];
91
92 var links = [
93 { source: 0, target: 1 }
94 ];
95
96 var svg = d3.select('body').append('svg')
97 .attr('width', width)
98 .attr('height', height);
99
100 var force = d3.layout.force()
101 .size([width, height])
102 .nodes(nodes)
103 .links(links);
104
105 force.linkDistance(width/2);
106
107
108 var link = svg.selectAll('.link')
109 .data(links)
110 .enter().append('line')
111 .attr('class', 'link');
112
113 var node = svg.selectAll('.node')
114 .data(nodes)
115 .enter().append('circle')
116 .attr('class', 'node');
117
118 force.start();
Simon Huntd5b96732016-07-08 13:22:27 -0700119 }
120
121 function destroy() {
122 $log.debug('Destroy topo force layout');
123 }
124
Simon Hunt98189192016-07-29 19:02:27 -0700125 // ========================== Temporary Code (to be deleted later)
126
127 function request(dir, rid) {
128 wss.sendEvent('topo2navRegion', {
129 dir: dir,
130 rid: rid
131 });
132 }
133
134 function doTmpCurrentLayout(data) {
135 var topdiv = d3.select('#topo2tmp');
136 var parentRegion = data.parent;
137 var span = topdiv.select('.parentRegion').select('span');
138 span.text(parentRegion || '[no parent]');
139 span.classed('nav-me', !!parentRegion);
140 }
141
142 function doTmpCurrentRegion(data) {
143 var topdiv = d3.select('#topo2tmp');
144 var span = topdiv.select('.thisRegion').select('span');
145 var div;
146
147 span.text(data.id);
148
149 div = topdiv.select('.subRegions').select('div');
150 data.subregions.forEach(function (r) {
151
152 function nav() {
153 request('down', r.id);
154 }
155
156 div.append('p')
157 .classed('nav-me', true)
158 .text(r.id)
159 .on('click', nav);
160 });
161
162 div = topdiv.select('.devices').select('div');
163 data.layerOrder.forEach(function (tag, idx) {
164 var devs = data.devices[idx];
165 devs.forEach(function (d) {
166 div.append('p')
167 .text('[' + tag + '] ' + d.id);
168 });
169
170 });
171
172 div = topdiv.select('.hosts').select('div');
173 data.layerOrder.forEach(function (tag, idx) {
174 var hosts = data.hosts[idx];
175 hosts.forEach(function (h) {
176 div.append('p')
177 .text('[' + tag + '] ' + h.id);
178 });
179 });
180
181 div = topdiv.select('.links').select('div');
182 var links = data.links;
183 links.forEach(function (lnk) {
184 div.append('p')
185 .text(lnk.id);
186 });
187 }
188
189 function doTmpPeerRegions(data) {
190
191 }
192
Simon Huntd5b96732016-07-08 13:22:27 -0700193 // ========================== Event Handlers
194
195 function allInstances(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100196 $log.debug('>> topo2AllInstances event:', data);
Simon Hunt98189192016-07-29 19:02:27 -0700197 doTmpCurrentLayout(data);
Steven Burrows57e24e92016-08-04 18:38:24 +0100198 t2is.allInstances(data);
Simon Huntd5b96732016-07-08 13:22:27 -0700199 }
200
201 function currentLayout(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100202 $log.debug('>> topo2CurrentLayout event:', data);
Simon Huntd5b96732016-07-08 13:22:27 -0700203 }
204
205 function currentRegion(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100206 $log.debug('>> topo2CurrentRegion event:', data);
Simon Hunt98189192016-07-29 19:02:27 -0700207 doTmpCurrentRegion(data);
Steven Burrows57e24e92016-08-04 18:38:24 +0100208 t2rs.addRegion(data);
Simon Hunt98189192016-07-29 19:02:27 -0700209 }
210
211 function topo2PeerRegions(data) {
212 $log.debug('>> topo2PeerRegions event:', data)
213 doTmpPeerRegions(data);
214 }
215
216 function topo2PeerRegions(data) {
217 $log.debug('>> topo2PeerRegions event:', data)
Simon Huntd5b96732016-07-08 13:22:27 -0700218 }
219
220 function startDone(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100221 $log.debug('>> topo2StartDone event:', data);
Simon Huntd5b96732016-07-08 13:22:27 -0700222 }
Steven Burrows57e24e92016-08-04 18:38:24 +0100223
224
225 function showMastership(masterId) {
226 if (!masterId) {
227 restoreLayerState();
228 } else {
229 showMastershipFor(masterId);
230 }
231 }
232
233 function restoreLayerState() {
234 // NOTE: this level of indirection required, for when we have
235 // the layer filter functionality re-implemented
236 suppressLayers(false);
237 }
238
239 // ========================== Main Service Definition
240
241 function showMastershipFor(id) {
242 suppressLayers(true);
243 node.each(function (n) {
244 if (n.master === id) {
245 n.el.classed('suppressedmax', false);
246 }
247 });
248 }
249
250 function supAmt(less) {
251 return less ? 'suppressed' : 'suppressedmax';
252 }
253
254 function suppressLayers(b, less) {
255 var cls = supAmt(less);
256 node.classed(cls, b);
257 // link.classed(cls, b);
258 }
259
Simon Huntd5b96732016-07-08 13:22:27 -0700260 // ========================== Main Service Definition
261
262 angular.module('ovTopo2')
263 .factory('Topo2ForceService',
Steven Burrows57e24e92016-08-04 18:38:24 +0100264 ['$log', 'WebSocketService', 'Topo2InstanceService', 'Topo2RegionService',
265 function (_$log_, _wss_, _t2is_, _t2rs_) {
Simon Huntd5b96732016-07-08 13:22:27 -0700266 $log = _$log_;
267 wss = _wss_;
Steven Burrows57e24e92016-08-04 18:38:24 +0100268 t2is = _t2is_;
269 t2rs = _t2rs_;
270
Simon Huntd5b96732016-07-08 13:22:27 -0700271 return {
Steven Burrows57e24e92016-08-04 18:38:24 +0100272
Simon Huntd5b96732016-07-08 13:22:27 -0700273 init: init,
Steven Burrows57e24e92016-08-04 18:38:24 +0100274
Simon Huntd5b96732016-07-08 13:22:27 -0700275 destroy: destroy,
276 topo2AllInstances: allInstances,
277 topo2CurrentLayout: currentLayout,
278 topo2CurrentRegion: currentRegion,
Steven Burrows57e24e92016-08-04 18:38:24 +0100279 topo2StartDone: startDone,
280
281 showMastership: showMastership,
282 topo2PeerRegions: topo2PeerRegions
Simon Huntd5b96732016-07-08 13:22:27 -0700283 };
284 }]);
285}());