blob: 1155ffa992580fb42124cbd9b698f858c6927dd8 [file] [log] [blame]
Simon Huntef1138d2015-02-19 17:14:03 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Simon Huntef1138d2015-02-19 17:14:03 -08003 *
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 Oblique View Module.
19 Provides functionality to view the topology as two planes (packet & optical)
20 from an oblique (side-on) perspective.
21 */
22
23(function () {
24 'use strict';
25
26 // injected refs
Steven Burrows1c2a9682017-07-14 16:52:46 +010027 var sus, flash;
Simon Huntef1138d2015-02-19 17:14:03 -080028
29 // api to topoForce
30 var api;
31 /*
Simon Huntc3c5b672015-02-20 11:32:13 -080032 force() // get ref to force layout object
33 zoomLayer() // get ref to zoom layer
34 nodeGBBox() // get bounding box of node group layer
Simon Huntef1138d2015-02-19 17:14:03 -080035 node() // get ref to D3 selection of nodes
36 link() // get ref to D3 selection of links
Simon Huntc3c5b672015-02-20 11:32:13 -080037 nodes() // get ref to network nodes array
38 tickStuff // ref to tick functions
39 nodeLock(b) // test-and-set nodeLock state
40 opacifyMap(b) // show or hide map layer
41 inLayer(d, layer) // return true if d in layer {'pkt'|'opt'}
Bri Prebilic Cole038aedd2015-07-13 15:25:16 -070042 calcLinkPos() // recomputes link pos based on node data
Simon Huntef1138d2015-02-19 17:14:03 -080043 */
44
Simon Huntc3c5b672015-02-20 11:32:13 -080045 // configuration
Steven Burrows1c2a9682017-07-14 16:52:46 +010046 var xsky = -.7, // x skew y factor
47 xsk = -35, // x skew angle
48 ysc = .5, // y scale
Simon Huntc3c5b672015-02-20 11:32:13 -080049 pad = 50,
50 time = 1500,
51 fill = {
Steven Burrows1c2a9682017-07-14 16:52:46 +010052 pkt: 'rgba(130,130,170,0.3)', // blue-ish
53 opt: 'rgba(170,130,170,0.3)', // magenta-ish
Simon Huntc3c5b672015-02-20 11:32:13 -080054 };
55
Simon Huntef1138d2015-02-19 17:14:03 -080056 // internal state
Simon Huntc3c5b672015-02-20 11:32:13 -080057 var oblique = false,
58 xffn = null,
59 plane = {},
60 oldNodeLock;
Simon Huntef1138d2015-02-19 17:14:03 -080061
Simon Hunt1603c692017-08-10 19:53:35 -070062 // function to be replaced by the localization bundle function
63 var topoLion = function (x) {
64 return '#tobq#' + x + '#';
65 };
Simon Hunt96f88c62015-02-19 17:57:25 -080066
Simon Huntc3c5b672015-02-20 11:32:13 -080067 function planeId(tag) {
68 return 'topo-obview-' + tag + 'Plane';
Simon Hunt96f88c62015-02-19 17:57:25 -080069 }
70
Simon Huntc3c5b672015-02-20 11:32:13 -080071 function ytfn(h, dir) {
72 return h * ysc * dir * 1.1;
73 }
74
75 function obXform(h, dir) {
76 var yt = ytfn(h, dir);
77 return sus.scale(1, ysc) + sus.translate(0, yt) + sus.skewX(xsk);
78 }
79
80 function noXform() {
Steven Burrows1c2a9682017-07-14 16:52:46 +010081 return sus.skewX(0) + sus.translate(0, 0) + sus.scale(1, 1);
Simon Huntc3c5b672015-02-20 11:32:13 -080082 }
83
84 function padBox(box, p) {
85 box.x -= p;
86 box.y -= p;
87 box.width += p*2;
88 box.height += p*2;
89 }
90
91 function toObliqueView() {
92 var box = api.nodeGBBox(),
93 ox, oy;
94
95 padBox(box, pad);
96
97 ox = box.x + box.width / 2;
98 oy = box.y + box.height / 2;
99
100 // remember node lock state, then lock the nodes down
101 oldNodeLock = api.nodeLock(true);
102 api.opacifyMap(false);
103
104 insertPlanes(ox, oy);
105
106 xffn = function (xy, dir) {
107 var yt = ytfn(box.height, dir),
108 ax = xy.x - ox,
109 ay = xy.y - oy,
110 x = ax + ay * xsky,
111 y = (ay + yt) * ysc;
Steven Burrows1c2a9682017-07-14 16:52:46 +0100112 return { x: ox + x, y: oy + y };
Simon Huntc3c5b672015-02-20 11:32:13 -0800113 };
114
115 showPlane('pkt', box, -1);
116 showPlane('opt', box, 1);
117 obTransitionNodes();
118 }
119
120 function toNormalView() {
121 xffn = null;
122
123 hidePlane('pkt');
124 hidePlane('opt');
125 obTransitionNodes();
126
127 removePlanes();
128
129 // restore node lock state
130 api.nodeLock(oldNodeLock);
131 api.opacifyMap(true);
132 }
133
134 function obTransitionNodes() {
135 // return the direction for the node
136 // -1 for pkt layer, 1 for optical layer
137 function dir(d) {
138 return api.inLayer(d, 'pkt') ? -1 : 1;
139 }
140
141 if (xffn) {
142 api.nodes().forEach(function (d) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100143 var oldxy = { x: d.x, y: d.y },
Simon Huntc3c5b672015-02-20 11:32:13 -0800144 coords = xffn(oldxy, dir(d));
145 d.oldxy = oldxy;
146 d.px = d.x = coords.x;
147 d.py = d.y = coords.y;
148 });
149 } else {
150 api.nodes().forEach(function (d) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100151 var old = d.oldxy || { x: d.x, y: d.y };
Simon Huntc3c5b672015-02-20 11:32:13 -0800152 d.px = d.x = old.x;
153 d.py = d.y = old.y;
154 delete d.oldxy;
155 });
156 }
157
158 api.node().transition()
159 .duration(time)
160 .attr(api.tickStuff.nodeAttr);
161 api.link().transition()
162 .duration(time)
Bri Prebilic Cole038aedd2015-07-13 15:25:16 -0700163 .call(api.calcLinkPos)
Bri Prebilic Cole80401762015-07-16 11:36:18 -0700164 .attr(api.tickStuff.linkAttr)
165 .call(api.applyNumLinkLabels);
Simon Huntc3c5b672015-02-20 11:32:13 -0800166 api.linkLabel().transition()
167 .duration(time)
168 .attr(api.tickStuff.linkLabelAttr);
169 }
170
171 function showPlane(tag, box, dir) {
172 // set box origin at center..
173 box.x = -box.width/2;
174 box.y = -box.height/2;
175
176 plane[tag].select('rect')
177 .attr(box)
178 .attr('opacity', 0)
179 .transition()
180 .duration(time)
181 .attr('opacity', 1)
182 .attr('transform', obXform(box.height, dir));
183 }
184
185 function hidePlane(tag) {
186 plane[tag].select('rect')
187 .transition()
188 .duration(time)
189 .attr('opacity', 0)
190 .attr('transform', noXform());
191 }
192
193 function insertPlanes(ox, oy) {
194 function ins(tag) {
195 var id = planeId(tag),
196 g = api.zoomLayer().insert('g', '#topo-G')
197 .attr('id', id)
Steven Burrows1c2a9682017-07-14 16:52:46 +0100198 .attr('transform', sus.translate(ox, oy));
Simon Huntc3c5b672015-02-20 11:32:13 -0800199 g.append('rect')
200 .attr('fill', fill[tag])
201 .attr('opacity', 0);
202 plane[tag] = g;
203 }
204 ins('opt');
205 ins('pkt');
206 }
207
208 function removePlanes() {
209 function rem(tag) {
210 var id = planeId(tag);
211 api.zoomLayer().select('#'+id)
212 .transition()
213 .duration(time + 50)
214 .remove();
215 delete plane[tag];
216 }
217 rem('opt');
218 rem('pkt');
219 }
220
Simon Hunt1603c692017-08-10 19:53:35 -0700221 // invoked after the localization bundle has been received from the server
222 function setLionBundle(bundle) {
223 topoLion = bundle;
224 }
Simon Huntc3c5b672015-02-20 11:32:13 -0800225
Simon Huntef1138d2015-02-19 17:14:03 -0800226// === -----------------------------------------------------
227// === MODULE DEFINITION ===
228
229angular.module('ovTopo')
230 .factory('TopoObliqueService',
Steven Burrows1c2a9682017-07-14 16:52:46 +0100231 ['SvgUtilService', 'FlashService',
Simon Huntef1138d2015-02-19 17:14:03 -0800232
Steven Burrows1c2a9682017-07-14 16:52:46 +0100233 function (_sus_, _flash_) {
Simon Huntc3c5b672015-02-20 11:32:13 -0800234 sus = _sus_;
Bri Prebilic Cole9cf1a8d2015-04-21 13:15:29 -0700235 flash = _flash_;
Simon Huntef1138d2015-02-19 17:14:03 -0800236
237 function initOblique(_api_) {
238 api = _api_;
239 }
240
241 function destroyOblique() { }
242
Simon Huntc3c5b672015-02-20 11:32:13 -0800243 function toggleOblique() {
244 oblique = !oblique;
245 if (oblique) {
246 api.force().stop();
Simon Hunt1603c692017-08-10 19:53:35 -0700247 flash.flash(topoLion('fl_oblique_view'));
Simon Huntc3c5b672015-02-20 11:32:13 -0800248 toObliqueView();
249 } else {
Simon Hunt1603c692017-08-10 19:53:35 -0700250 flash.flash(topoLion('fl_normal_view'));
Simon Huntc3c5b672015-02-20 11:32:13 -0800251 toNormalView();
252 }
253 }
254
Simon Huntef1138d2015-02-19 17:14:03 -0800255 return {
256 initOblique: initOblique,
Simon Hunt96f88c62015-02-19 17:57:25 -0800257 destroyOblique: destroyOblique,
258
Simon Huntc3c5b672015-02-20 11:32:13 -0800259 isOblique: function () { return oblique; },
Steven Burrows1c2a9682017-07-14 16:52:46 +0100260 toggleOblique: toggleOblique,
Simon Hunt1603c692017-08-10 19:53:35 -0700261 setLionBundle: setLionBundle,
Simon Huntef1138d2015-02-19 17:14:03 -0800262 };
263 }]);
264}());