Committed by
Gerrit Code Review
GUI -- TopoView - Re-instated the oblique view function. (Keystroke 'Z').
Change-Id: I1bc4c11590660142a6bc9f5f71c06a664dbfa80b
Showing
6 changed files
with
218 additions
and
17 deletions
... | @@ -204,6 +204,11 @@ | ... | @@ -204,6 +204,11 @@ |
204 | return ms.loadMapInto(mapG, '*continental_us'); | 204 | return ms.loadMapInto(mapG, '*continental_us'); |
205 | } | 205 | } |
206 | 206 | ||
207 | + function opacifyMap(b) { | ||
208 | + mapG.transition() | ||
209 | + .duration(1000) | ||
210 | + .attr('opacity', b ? 1 : 0); | ||
211 | + } | ||
207 | 212 | ||
208 | // --- Controller Definition ----------------------------------------- | 213 | // --- Controller Definition ----------------------------------------- |
209 | 214 | ||
... | @@ -226,6 +231,8 @@ | ... | @@ -226,6 +231,8 @@ |
226 | // provides function calls back into this space | 231 | // provides function calls back into this space |
227 | showNoDevs: showNoDevs, | 232 | showNoDevs: showNoDevs, |
228 | projection: function () { return projection; }, | 233 | projection: function () { return projection; }, |
234 | + zoomLayer: function () { return zoomLayer; }, | ||
235 | + opacifyMap: opacifyMap, | ||
229 | sendEvent: _tes_.sendEvent | 236 | sendEvent: _tes_.sendEvent |
230 | }; | 237 | }; |
231 | 238 | ... | ... |
... | @@ -117,7 +117,6 @@ | ... | @@ -117,7 +117,6 @@ |
117 | return btnG ? btnG.selected : ''; | 117 | return btnG ? btnG.selected : ''; |
118 | } | 118 | } |
119 | 119 | ||
120 | - // code to manipulate the nodes and links as per the filter settings | ||
121 | function inLayer(d, layer) { | 120 | function inLayer(d, layer) { |
122 | var type = d.class === 'link' ? d.type() : d.type, | 121 | var type = d.class === 'link' ? d.type() : d.type, |
123 | look = layerLookup[d.class], | 122 | look = layerLookup[d.class], |
... | @@ -186,7 +185,8 @@ | ... | @@ -186,7 +185,8 @@ |
186 | destroyFilter: destroyFilter, | 185 | destroyFilter: destroyFilter, |
187 | 186 | ||
188 | clickAction: clickAction, | 187 | clickAction: clickAction, |
189 | - selected: selected | 188 | + selected: selected, |
189 | + inLayer: inLayer | ||
190 | }; | 190 | }; |
191 | }]); | 191 | }]); |
192 | }()); | 192 | }()); | ... | ... |
... | @@ -76,7 +76,6 @@ | ... | @@ -76,7 +76,6 @@ |
76 | hostLabelIndex = 0, // for host label cycling | 76 | hostLabelIndex = 0, // for host label cycling |
77 | showHosts = false, // whether hosts are displayed | 77 | showHosts = false, // whether hosts are displayed |
78 | showOffline = true, // whether offline devices are displayed | 78 | showOffline = true, // whether offline devices are displayed |
79 | - oblique = false, // whether we are in the oblique view | ||
80 | nodeLock = false, // whether nodes can be dragged or not (locked) | 79 | nodeLock = false, // whether nodes can be dragged or not (locked) |
81 | dim; // the dimensions of the force layout [w,h] | 80 | dim; // the dimensions of the force layout [w,h] |
82 | 81 | ||
... | @@ -965,13 +964,13 @@ | ... | @@ -965,13 +964,13 @@ |
965 | // force layout tick function | 964 | // force layout tick function |
966 | 965 | ||
967 | function fResume() { | 966 | function fResume() { |
968 | - if (!oblique) { | 967 | + if (!tos.isOblique()) { |
969 | force.resume(); | 968 | force.resume(); |
970 | } | 969 | } |
971 | } | 970 | } |
972 | 971 | ||
973 | function fStart() { | 972 | function fStart() { |
974 | - if (!oblique) { | 973 | + if (!tos.isOblique()) { |
975 | force.start(); | 974 | force.start(); |
976 | } | 975 | } |
977 | } | 976 | } |
... | @@ -1084,10 +1083,23 @@ | ... | @@ -1084,10 +1083,23 @@ |
1084 | } | 1083 | } |
1085 | } | 1084 | } |
1086 | 1085 | ||
1087 | - function mkObliqueApi(uplink) { | 1086 | + function mkObliqueApi(uplink, fltr) { |
1088 | return { | 1087 | return { |
1088 | + force: function() { return force; }, | ||
1089 | + zoomLayer: uplink.zoomLayer, | ||
1090 | + nodeGBBox: function() { return nodeG.node().getBBox(); }, | ||
1089 | node: function () { return node; }, | 1091 | node: function () { return node; }, |
1090 | - link: function () { return link; } | 1092 | + link: function () { return link; }, |
1093 | + linkLabel: function () { return linkLabel; }, | ||
1094 | + nodes: function () { return network.nodes; }, | ||
1095 | + tickStuff: tickStuff, | ||
1096 | + nodeLock: function (b) { | ||
1097 | + var old = nodeLock; | ||
1098 | + nodeLock = b; | ||
1099 | + return old; | ||
1100 | + }, | ||
1101 | + opacifyMap: uplink.opacifyMap, | ||
1102 | + inLayer: fltr.inLayer | ||
1091 | }; | 1103 | }; |
1092 | } | 1104 | } |
1093 | 1105 | ||
... | @@ -1140,7 +1152,7 @@ | ... | @@ -1140,7 +1152,7 @@ |
1140 | tms.initModel(mkModelApi(uplink), dim); | 1152 | tms.initModel(mkModelApi(uplink), dim); |
1141 | tss.initSelect(mkSelectApi(uplink)); | 1153 | tss.initSelect(mkSelectApi(uplink)); |
1142 | tts.initTraffic(mkTrafficApi(uplink)); | 1154 | tts.initTraffic(mkTrafficApi(uplink)); |
1143 | - tos.initOblique(mkObliqueApi(uplink)); | 1155 | + tos.initOblique(mkObliqueApi(uplink, fltr)); |
1144 | fltr.initFilter(mkFilterApi(uplink), d3.select('#mast-right')); | 1156 | fltr.initFilter(mkFilterApi(uplink), d3.select('#mast-right')); |
1145 | 1157 | ||
1146 | settings = angular.extend({}, defaultSettings, opts); | 1158 | settings = angular.extend({}, defaultSettings, opts); | ... | ... |
... | @@ -24,35 +24,206 @@ | ... | @@ -24,35 +24,206 @@ |
24 | 'use strict'; | 24 | 'use strict'; |
25 | 25 | ||
26 | // injected refs | 26 | // injected refs |
27 | - var $log, fs; | 27 | + var $log, fs, sus, ts; |
28 | 28 | ||
29 | // api to topoForce | 29 | // api to topoForce |
30 | var api; | 30 | var api; |
31 | /* | 31 | /* |
32 | + force() // get ref to force layout object | ||
33 | + zoomLayer() // get ref to zoom layer | ||
34 | + nodeGBBox() // get bounding box of node group layer | ||
32 | node() // get ref to D3 selection of nodes | 35 | node() // get ref to D3 selection of nodes |
33 | link() // get ref to D3 selection of links | 36 | link() // get ref to D3 selection of links |
37 | + 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'} | ||
34 | */ | 42 | */ |
35 | 43 | ||
44 | + // configuration | ||
45 | + var xsky = -.7, // x skew y factor | ||
46 | + xsk = -35, // x skew angle | ||
47 | + ysc = .5, // y scale | ||
48 | + pad = 50, | ||
49 | + time = 1500, | ||
50 | + fill = { | ||
51 | + pkt: 'rgba(130,130,170,0.3)', // blue-ish | ||
52 | + opt: 'rgba(170,130,170,0.3)' // magenta-ish | ||
53 | + }; | ||
54 | + | ||
36 | // internal state | 55 | // internal state |
37 | - var foo; | 56 | + var oblique = false, |
57 | + xffn = null, | ||
58 | + plane = {}, | ||
59 | + oldNodeLock; | ||
60 | + | ||
38 | 61 | ||
39 | - // ========================== | 62 | + function planeId(tag) { |
63 | + return 'topo-obview-' + tag + 'Plane'; | ||
64 | + } | ||
40 | 65 | ||
66 | + function ytfn(h, dir) { | ||
67 | + return h * ysc * dir * 1.1; | ||
68 | + } | ||
41 | 69 | ||
42 | - function toggleOblique() { | 70 | + function obXform(h, dir) { |
43 | - $log.log("TOGGLING OBLIQUE VIEW"); | 71 | + var yt = ytfn(h, dir); |
72 | + return sus.scale(1, ysc) + sus.translate(0, yt) + sus.skewX(xsk); | ||
73 | + } | ||
74 | + | ||
75 | + function noXform() { | ||
76 | + return sus.skewX(0) + sus.translate(0,0) + sus.scale(1,1); | ||
77 | + } | ||
78 | + | ||
79 | + function padBox(box, p) { | ||
80 | + box.x -= p; | ||
81 | + box.y -= p; | ||
82 | + box.width += p*2; | ||
83 | + box.height += p*2; | ||
84 | + } | ||
85 | + | ||
86 | + function toObliqueView() { | ||
87 | + var box = api.nodeGBBox(), | ||
88 | + ox, oy; | ||
89 | + | ||
90 | + padBox(box, pad); | ||
91 | + | ||
92 | + ox = box.x + box.width / 2; | ||
93 | + oy = box.y + box.height / 2; | ||
94 | + | ||
95 | + // remember node lock state, then lock the nodes down | ||
96 | + oldNodeLock = api.nodeLock(true); | ||
97 | + api.opacifyMap(false); | ||
98 | + | ||
99 | + insertPlanes(ox, oy); | ||
100 | + | ||
101 | + xffn = function (xy, dir) { | ||
102 | + var yt = ytfn(box.height, dir), | ||
103 | + ax = xy.x - ox, | ||
104 | + ay = xy.y - oy, | ||
105 | + x = ax + ay * xsky, | ||
106 | + y = (ay + yt) * ysc; | ||
107 | + return {x: ox + x, y: oy + y}; | ||
108 | + }; | ||
109 | + | ||
110 | + showPlane('pkt', box, -1); | ||
111 | + showPlane('opt', box, 1); | ||
112 | + obTransitionNodes(); | ||
113 | + } | ||
114 | + | ||
115 | + function toNormalView() { | ||
116 | + xffn = null; | ||
117 | + | ||
118 | + hidePlane('pkt'); | ||
119 | + hidePlane('opt'); | ||
120 | + obTransitionNodes(); | ||
121 | + | ||
122 | + removePlanes(); | ||
123 | + | ||
124 | + // restore node lock state | ||
125 | + api.nodeLock(oldNodeLock); | ||
126 | + api.opacifyMap(true); | ||
127 | + } | ||
128 | + | ||
129 | + function obTransitionNodes() { | ||
130 | + // return the direction for the node | ||
131 | + // -1 for pkt layer, 1 for optical layer | ||
132 | + function dir(d) { | ||
133 | + return api.inLayer(d, 'pkt') ? -1 : 1; | ||
134 | + } | ||
135 | + | ||
136 | + if (xffn) { | ||
137 | + api.nodes().forEach(function (d) { | ||
138 | + var oldxy = {x: d.x, y: d.y}, | ||
139 | + coords = xffn(oldxy, dir(d)); | ||
140 | + d.oldxy = oldxy; | ||
141 | + d.px = d.x = coords.x; | ||
142 | + d.py = d.y = coords.y; | ||
143 | + }); | ||
144 | + } else { | ||
145 | + api.nodes().forEach(function (d) { | ||
146 | + var old = d.oldxy || {x: d.x, y: d.y}; | ||
147 | + d.px = d.x = old.x; | ||
148 | + d.py = d.y = old.y; | ||
149 | + delete d.oldxy; | ||
150 | + }); | ||
151 | + } | ||
152 | + | ||
153 | + api.node().transition() | ||
154 | + .duration(time) | ||
155 | + .attr(api.tickStuff.nodeAttr); | ||
156 | + api.link().transition() | ||
157 | + .duration(time) | ||
158 | + .attr(api.tickStuff.linkAttr); | ||
159 | + api.linkLabel().transition() | ||
160 | + .duration(time) | ||
161 | + .attr(api.tickStuff.linkLabelAttr); | ||
162 | + } | ||
163 | + | ||
164 | + function showPlane(tag, box, dir) { | ||
165 | + // set box origin at center.. | ||
166 | + box.x = -box.width/2; | ||
167 | + box.y = -box.height/2; | ||
168 | + | ||
169 | + plane[tag].select('rect') | ||
170 | + .attr(box) | ||
171 | + .attr('opacity', 0) | ||
172 | + .transition() | ||
173 | + .duration(time) | ||
174 | + .attr('opacity', 1) | ||
175 | + .attr('transform', obXform(box.height, dir)); | ||
176 | + } | ||
177 | + | ||
178 | + function hidePlane(tag) { | ||
179 | + plane[tag].select('rect') | ||
180 | + .transition() | ||
181 | + .duration(time) | ||
182 | + .attr('opacity', 0) | ||
183 | + .attr('transform', noXform()); | ||
44 | } | 184 | } |
45 | 185 | ||
186 | + function insertPlanes(ox, oy) { | ||
187 | + function ins(tag) { | ||
188 | + var id = planeId(tag), | ||
189 | + g = api.zoomLayer().insert('g', '#topo-G') | ||
190 | + .attr('id', id) | ||
191 | + .attr('transform', sus.translate(ox,oy)); | ||
192 | + g.append('rect') | ||
193 | + .attr('fill', fill[tag]) | ||
194 | + .attr('opacity', 0); | ||
195 | + plane[tag] = g; | ||
196 | + } | ||
197 | + ins('opt'); | ||
198 | + ins('pkt'); | ||
199 | + } | ||
200 | + | ||
201 | + function removePlanes() { | ||
202 | + function rem(tag) { | ||
203 | + var id = planeId(tag); | ||
204 | + api.zoomLayer().select('#'+id) | ||
205 | + .transition() | ||
206 | + .duration(time + 50) | ||
207 | + .remove(); | ||
208 | + delete plane[tag]; | ||
209 | + } | ||
210 | + rem('opt'); | ||
211 | + rem('pkt'); | ||
212 | + } | ||
213 | + | ||
214 | + | ||
46 | // === ----------------------------------------------------- | 215 | // === ----------------------------------------------------- |
47 | // === MODULE DEFINITION === | 216 | // === MODULE DEFINITION === |
48 | 217 | ||
49 | angular.module('ovTopo') | 218 | angular.module('ovTopo') |
50 | .factory('TopoObliqueService', | 219 | .factory('TopoObliqueService', |
51 | - ['$log', 'FnService', | 220 | + ['$log', 'FnService', 'SvgUtilService', 'ThemeService', |
52 | 221 | ||
53 | - function (_$log_, _fs_) { | 222 | + function (_$log_, _fs_, _sus_, _ts_) { |
54 | $log = _$log_; | 223 | $log = _$log_; |
55 | fs = _fs_; | 224 | fs = _fs_; |
225 | + sus = _sus_; | ||
226 | + ts = _ts_; | ||
56 | 227 | ||
57 | function initOblique(_api_) { | 228 | function initOblique(_api_) { |
58 | api = _api_; | 229 | api = _api_; |
... | @@ -60,10 +231,21 @@ angular.module('ovTopo') | ... | @@ -60,10 +231,21 @@ angular.module('ovTopo') |
60 | 231 | ||
61 | function destroyOblique() { } | 232 | function destroyOblique() { } |
62 | 233 | ||
234 | + function toggleOblique() { | ||
235 | + oblique = !oblique; | ||
236 | + if (oblique) { | ||
237 | + api.force().stop(); | ||
238 | + toObliqueView(); | ||
239 | + } else { | ||
240 | + toNormalView(); | ||
241 | + } | ||
242 | + } | ||
243 | + | ||
63 | return { | 244 | return { |
64 | initOblique: initOblique, | 245 | initOblique: initOblique, |
65 | destroyOblique: destroyOblique, | 246 | destroyOblique: destroyOblique, |
66 | 247 | ||
248 | + isOblique: function () { return oblique; }, | ||
67 | toggleOblique: toggleOblique | 249 | toggleOblique: toggleOblique |
68 | }; | 250 | }; |
69 | }]); | 251 | }]); | ... | ... |
... | @@ -54,7 +54,7 @@ describe('factory: view/topo/topoFilter.js', function() { | ... | @@ -54,7 +54,7 @@ describe('factory: view/topo/topoFilter.js', function() { |
54 | it('should define api functions', function () { | 54 | it('should define api functions', function () { |
55 | expect(fs.areFunctions(fltr, [ | 55 | expect(fs.areFunctions(fltr, [ |
56 | 'initFilter', 'destroyFilter', | 56 | 'initFilter', 'destroyFilter', |
57 | - 'clickAction', 'selected' | 57 | + 'clickAction', 'selected', 'inLayer', |
58 | ])).toBeTruthy(); | 58 | ])).toBeTruthy(); |
59 | }); | 59 | }); |
60 | 60 | ... | ... |
... | @@ -34,7 +34,7 @@ describe('factory: view/topo/topoOblique.js', function() { | ... | @@ -34,7 +34,7 @@ describe('factory: view/topo/topoOblique.js', function() { |
34 | 34 | ||
35 | it('should define api functions', function () { | 35 | it('should define api functions', function () { |
36 | expect(fs.areFunctions(tos, [ | 36 | expect(fs.areFunctions(tos, [ |
37 | - 'initOblique', 'destroyOblique', 'toggleOblique' | 37 | + 'initOblique', 'destroyOblique', 'isOblique', 'toggleOblique' |
38 | ])).toBeTruthy(); | 38 | ])).toBeTruthy(); |
39 | }); | 39 | }); |
40 | 40 | ... | ... |
-
Please register or login to post a comment