blob: 57a5f89b8af96cd07849cd64d6056fad398b54b8 [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
Steven Burrowsdfa52b02016-09-02 13:50:43 +010029 var t2is, t2rs, t2ls, t2vs, t2bcs;
Steven Burrows1aa4f582016-12-13 15:05:41 -050030 var svg, forceG, uplink, dim, opts, zoomer;
Simon Huntd5b96732016-07-08 13:22:27 -070031
Steven Burrowsdfa52b02016-09-02 13:50:43 +010032 // D3 Selections
33 var node;
34
Simon Huntd5b96732016-07-08 13:22:27 -070035 // ========================== Helper Functions
36
Steven Burrows1aa4f582016-12-13 15:05:41 -050037 function init(_svg_, _forceG_, _uplink_, _dim_, _zoomer_, _opts_) {
Steven Burrowsec1f45c2016-08-08 16:14:41 +010038 svg = _svg_;
39 forceG = _forceG_;
40 uplink = _uplink_;
41 dim = _dim_;
Steven Burrowsdfa52b02016-09-02 13:50:43 +010042 opts = _opts_;
Steven Burrows1aa4f582016-12-13 15:05:41 -050043 zoomer = _zoomer_;
Steven Burrowsdfa52b02016-09-02 13:50:43 +010044
Steven Burrows1aa4f582016-12-13 15:05:41 -050045 t2ls.init(svg, forceG, uplink, dim, zoomer, opts);
Simon Huntd5b96732016-07-08 13:22:27 -070046 }
47
48 function destroy() {
49 $log.debug('Destroy topo force layout');
50 }
51
Simon Hunt98189192016-07-29 19:02:27 -070052 // ========================== Temporary Code (to be deleted later)
53
54 function request(dir, rid) {
55 wss.sendEvent('topo2navRegion', {
56 dir: dir,
57 rid: rid
58 });
59 }
60
61 function doTmpCurrentLayout(data) {
62 var topdiv = d3.select('#topo2tmp');
63 var parentRegion = data.parent;
64 var span = topdiv.select('.parentRegion').select('span');
65 span.text(parentRegion || '[no parent]');
Steven Burrowsdfa52b02016-09-02 13:50:43 +010066 span.classed('nav-me', Boolean(parentRegion));
Simon Hunt98189192016-07-29 19:02:27 -070067 }
68
69 function doTmpCurrentRegion(data) {
70 var topdiv = d3.select('#topo2tmp');
71 var span = topdiv.select('.thisRegion').select('span');
72 var div;
73
74 span.text(data.id);
75
76 div = topdiv.select('.subRegions').select('div');
77 data.subregions.forEach(function (r) {
78
79 function nav() {
80 request('down', r.id);
81 }
82
83 div.append('p')
84 .classed('nav-me', true)
85 .text(r.id)
86 .on('click', nav);
87 });
88
89 div = topdiv.select('.devices').select('div');
90 data.layerOrder.forEach(function (tag, idx) {
91 var devs = data.devices[idx];
92 devs.forEach(function (d) {
93 div.append('p')
94 .text('[' + tag + '] ' + d.id);
95 });
96
97 });
98
99 div = topdiv.select('.hosts').select('div');
100 data.layerOrder.forEach(function (tag, idx) {
101 var hosts = data.hosts[idx];
102 hosts.forEach(function (h) {
103 div.append('p')
104 .text('[' + tag + '] ' + h.id);
105 });
106 });
107
108 div = topdiv.select('.links').select('div');
109 var links = data.links;
110 links.forEach(function (lnk) {
111 div.append('p')
112 .text(lnk.id);
113 });
114 }
115
116 function doTmpPeerRegions(data) {
117
118 }
119
Simon Huntd5b96732016-07-08 13:22:27 -0700120 // ========================== Event Handlers
121
122 function allInstances(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100123 $log.debug('>> topo2AllInstances event:', data);
Simon Hunt98189192016-07-29 19:02:27 -0700124 doTmpCurrentLayout(data);
Steven Burrows57e24e92016-08-04 18:38:24 +0100125 t2is.allInstances(data);
Simon Huntd5b96732016-07-08 13:22:27 -0700126 }
127
128 function currentLayout(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100129 $log.debug('>> topo2CurrentLayout event:', data);
Steven Burrowsaf3159d2016-08-25 14:54:30 +0100130 t2bcs.addBreadcrumb(data.crumbs);
Simon Huntd5b96732016-07-08 13:22:27 -0700131 }
132
133 function currentRegion(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100134 $log.debug('>> topo2CurrentRegion event:', data);
Simon Hunt98189192016-07-29 19:02:27 -0700135 doTmpCurrentRegion(data);
Steven Burrows57e24e92016-08-04 18:38:24 +0100136 t2rs.addRegion(data);
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100137 t2ls.createForceLayout();
Simon Hunt98189192016-07-29 19:02:27 -0700138 }
139
140 function topo2PeerRegions(data) {
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100141 $log.debug('>> topo2PeerRegions event:', data);
Simon Hunt98189192016-07-29 19:02:27 -0700142 doTmpPeerRegions(data);
143 }
144
Simon Huntd5b96732016-07-08 13:22:27 -0700145 function startDone(data) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100146 $log.debug('>> topo2StartDone event:', data);
Simon Huntd5b96732016-07-08 13:22:27 -0700147 }
Steven Burrows57e24e92016-08-04 18:38:24 +0100148
Simon Hunt537bc762016-12-20 12:15:13 -0800149 function modelEvent(data) {
150 $log.debug('>> topo2UiModelEvent event:', data);
151 // TODO: Interpret the event and update our topo model state (if needed)
152 // To Decide: Can we assume that the server will only send events
153 // related to objects that we are currently showing?
154 // (e.g. filtered by subregion contents?)
155 }
156
Steven Burrows57e24e92016-08-04 18:38:24 +0100157 function showMastership(masterId) {
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100158 if (masterId) {
Steven Burrows57e24e92016-08-04 18:38:24 +0100159 showMastershipFor(masterId);
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100160 } else {
161 restoreLayerState();
Steven Burrows57e24e92016-08-04 18:38:24 +0100162 }
163 }
164
165 function restoreLayerState() {
166 // NOTE: this level of indirection required, for when we have
167 // the layer filter functionality re-implemented
168 suppressLayers(false);
169 }
170
171 // ========================== Main Service Definition
172
173 function showMastershipFor(id) {
174 suppressLayers(true);
175 node.each(function (n) {
176 if (n.master === id) {
177 n.el.classed('suppressedmax', false);
178 }
179 });
180 }
181
182 function supAmt(less) {
183 return less ? 'suppressed' : 'suppressedmax';
184 }
185
186 function suppressLayers(b, less) {
187 var cls = supAmt(less);
188 node.classed(cls, b);
189 // link.classed(cls, b);
190 }
191
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100192 function newDim(_dim_) {
193 dim = _dim_;
194 t2vs.newDim(dim);
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100195 }
196
Simon Huntd5b96732016-07-08 13:22:27 -0700197 // ========================== Main Service Definition
198
Steven Burrows1c5c8612016-10-05 13:45:13 -0500199 function update(elements) {
200 angular.forEach(elements, function (el) {
201 el.update();
202 });
203 }
204
Steven Burrows37549ee2016-09-21 14:41:39 +0100205 function updateNodes() {
Steven Burrows1c5c8612016-10-05 13:45:13 -0500206 update(t2rs.regionNodes());
207 }
208
209 function updateLinks() {
210 update(t2rs.regionLinks());
211 }
212
213 function resetAllLocations() {
214 var nodes = t2rs.regionNodes();
215
216 angular.forEach(nodes, function (node) {
217 node.resetPosition();
218 });
219
220 t2ls.update();
221 t2ls.tick();
222 }
223
224 function unpin() {
225 var hovered = t2rs.filterRegionNodes(function (model) {
226 return model.get('hovered');
227 });
228
229 angular.forEach(hovered, function (model) {
230 model.fixed = false;
231 model.el.classed('fixed', false);
Steven Burrows0616e802016-10-06 21:45:07 -0500232 });
Steven Burrows37549ee2016-09-21 14:41:39 +0100233 }
234
Simon Huntd5b96732016-07-08 13:22:27 -0700235 angular.module('ovTopo2')
236 .factory('Topo2ForceService',
Steven Burrows1c5c8612016-10-05 13:45:13 -0500237 ['$log', 'WebSocketService', 'Topo2InstanceService',
238 'Topo2RegionService', 'Topo2LayoutService', 'Topo2ViewService',
239 'Topo2BreadcrumbService', 'Topo2ZoomService',
240 function (_$log_, _wss_, _t2is_, _t2rs_, _t2ls_,
241 _t2vs_, _t2bcs_, zoomService) {
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100242
Simon Huntd5b96732016-07-08 13:22:27 -0700243 $log = _$log_;
244 wss = _wss_;
Steven Burrows57e24e92016-08-04 18:38:24 +0100245 t2is = _t2is_;
246 t2rs = _t2rs_;
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100247 t2ls = _t2ls_;
248 t2vs = _t2vs_;
Steven Burrowsaf3159d2016-08-25 14:54:30 +0100249 t2bcs = _t2bcs_;
Steven Burrows57e24e92016-08-04 18:38:24 +0100250
Steven Burrows0616e802016-10-06 21:45:07 -0500251 var onZoom = function () {
252 var nodes = [].concat(
253 t2rs.regionNodes(),
254 t2rs.regionLinks()
255 );
256
257 angular.forEach(nodes, function (node) {
258 node.setScale();
259 });
260 };
261
262 zoomService.addZoomEventListener(onZoom);
263
Simon Huntd5b96732016-07-08 13:22:27 -0700264 return {
Steven Burrows57e24e92016-08-04 18:38:24 +0100265
Simon Huntd5b96732016-07-08 13:22:27 -0700266 init: init,
Steven Burrowsec1f45c2016-08-08 16:14:41 +0100267 newDim: newDim,
Steven Burrows57e24e92016-08-04 18:38:24 +0100268
Simon Huntd5b96732016-07-08 13:22:27 -0700269 destroy: destroy,
270 topo2AllInstances: allInstances,
271 topo2CurrentLayout: currentLayout,
272 topo2CurrentRegion: currentRegion,
Steven Burrows57e24e92016-08-04 18:38:24 +0100273 topo2StartDone: startDone,
274
Simon Hunt537bc762016-12-20 12:15:13 -0800275 topo2UiModelEvent: modelEvent,
276
Steven Burrows57e24e92016-08-04 18:38:24 +0100277 showMastership: showMastership,
Steven Burrows37549ee2016-09-21 14:41:39 +0100278 topo2PeerRegions: topo2PeerRegions,
279
Steven Burrows1c5c8612016-10-05 13:45:13 -0500280 updateNodes: updateNodes,
281 updateLinks: updateLinks,
282 resetAllLocations: resetAllLocations,
283 unpin: unpin
Simon Huntd5b96732016-07-08 13:22:27 -0700284 };
285 }]);
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100286})();