GUI -- TopoView - added node selection logic.
- added inArray() and removeFromArray() functions to FnService. Change-Id: I0e9631fa9e5865cb171e8d505f45c1963a1903dc
Showing
4 changed files
with
169 additions
and
14 deletions
... | @@ -117,6 +117,32 @@ | ... | @@ -117,6 +117,32 @@ |
117 | return -1; | 117 | return -1; |
118 | } | 118 | } |
119 | 119 | ||
120 | + // search through array to find (the first occurrence of) item, | ||
121 | + // returning its index if found; otherwise returning -1. | ||
122 | + function inArray(item, array) { | ||
123 | + var i; | ||
124 | + if (isA(array)) { | ||
125 | + for (i=0; i<array.length; i++) { | ||
126 | + if (array[i] === item) { | ||
127 | + return i; | ||
128 | + } | ||
129 | + } | ||
130 | + } | ||
131 | + return -1; | ||
132 | + } | ||
133 | + | ||
134 | + // remove (the first occurrence of) the specified item from the given | ||
135 | + // array, if any. Return true if the removal was made; false otherwise. | ||
136 | + function removeFromArray(item, array) { | ||
137 | + var found = false, | ||
138 | + i = inArray(item, array); | ||
139 | + if (i >= 0) { | ||
140 | + array.splice(i, 1); | ||
141 | + found = true; | ||
142 | + } | ||
143 | + return found; | ||
144 | + } | ||
145 | + | ||
120 | angular.module('onosUtil') | 146 | angular.module('onosUtil') |
121 | .factory('FnService', ['$window', function (_$window_) { | 147 | .factory('FnService', ['$window', function (_$window_) { |
122 | $window = _$window_; | 148 | $window = _$window_; |
... | @@ -130,7 +156,9 @@ | ... | @@ -130,7 +156,9 @@ |
130 | areFunctions: areFunctions, | 156 | areFunctions: areFunctions, |
131 | areFunctionsNonStrict: areFunctionsNonStrict, | 157 | areFunctionsNonStrict: areFunctionsNonStrict, |
132 | windowSize: windowSize, | 158 | windowSize: windowSize, |
133 | - find: find | 159 | + find: find, |
160 | + inArray: inArray, | ||
161 | + removeFromArray: removeFromArray | ||
134 | }; | 162 | }; |
135 | }]); | 163 | }]); |
136 | 164 | ... | ... |
... | @@ -111,8 +111,7 @@ | ... | @@ -111,8 +111,7 @@ |
111 | <div id="quickhelp"></div> | 111 | <div id="quickhelp"></div> |
112 | <div id="veil" | 112 | <div id="veil" |
113 | resize | 113 | resize |
114 | - ng-style="resizeWithOffset(0, 0)" | 114 | + ng-style="resizeWithOffset(0, 0)"></div> |
115 | - ></div> | ||
116 | </div> | 115 | </div> |
117 | </body> | 116 | </body> |
118 | </html> | 117 | </html> | ... | ... |
... | @@ -77,7 +77,9 @@ | ... | @@ -77,7 +77,9 @@ |
77 | oblique = false, // whether we are in the oblique view | 77 | oblique = false, // whether we are in the oblique view |
78 | nodeLock = false, // whether nodes can be dragged or not (locked) | 78 | nodeLock = false, // whether nodes can be dragged or not (locked) |
79 | width, height, // the width and height of the force layout | 79 | width, height, // the width and height of the force layout |
80 | - hovered; // the node over which the mouse is hovering | 80 | + hovered, // the node over which the mouse is hovering |
81 | + selections = {}, // what is currently selected | ||
82 | + selectOrder = []; // the order in which we made selections | ||
81 | 83 | ||
82 | // SVG elements; | 84 | // SVG elements; |
83 | var linkG, linkLabelG, nodeG; | 85 | var linkG, linkLabelG, nodeG; |
... | @@ -1323,15 +1325,77 @@ | ... | @@ -1323,15 +1325,77 @@ |
1323 | } | 1325 | } |
1324 | 1326 | ||
1325 | 1327 | ||
1328 | + function updateDetailPanel() { | ||
1329 | + // TODO update detail panel | ||
1330 | + $log.debug("TODO: updateDetailPanel() ..."); | ||
1331 | + } | ||
1332 | + | ||
1333 | + | ||
1334 | + // ========================== | ||
1335 | + // === SELECTION / DESELECTION | ||
1336 | + | ||
1337 | + function selectObject(obj) { | ||
1338 | + var el = this, | ||
1339 | + ev = d3.event.sourceEvent, | ||
1340 | + n; | ||
1341 | + | ||
1342 | + if (zoomingOrPanning(ev)) { | ||
1343 | + return; | ||
1344 | + } | ||
1345 | + | ||
1346 | + if (el) { | ||
1347 | + n = d3.select(el); | ||
1348 | + } else { | ||
1349 | + node.each(function (d) { | ||
1350 | + if (d == obj) { | ||
1351 | + n = d3.select(el = this); | ||
1352 | + } | ||
1353 | + }); | ||
1354 | + } | ||
1355 | + if (!n) return; | ||
1356 | + | ||
1357 | + if (ev.shiftKey && n.classed('selected')) { | ||
1358 | + deselectObject(obj.id); | ||
1359 | + updateDetailPanel(); | ||
1360 | + return; | ||
1361 | + } | ||
1362 | + | ||
1363 | + if (!ev.shiftKey) { | ||
1364 | + deselectAll(); | ||
1365 | + } | ||
1366 | + | ||
1367 | + selections[obj.id] = { obj: obj, el: el }; | ||
1368 | + selectOrder.push(obj.id); | ||
1369 | + | ||
1370 | + n.classed('selected', true); | ||
1371 | + updateDeviceColors(obj); | ||
1372 | + updateDetailPanel(); | ||
1373 | + } | ||
1374 | + | ||
1375 | + function deselectObject(id) { | ||
1376 | + var obj = selections[id]; | ||
1377 | + if (obj) { | ||
1378 | + d3.select(obj.el).classed('selected', false); | ||
1379 | + delete selections[id]; | ||
1380 | + fs.removeFromArray(id, selectOrder); | ||
1381 | + updateDeviceColors(obj.obj); | ||
1382 | + } | ||
1383 | + } | ||
1384 | + | ||
1385 | + function deselectAll() { | ||
1386 | + // deselect all nodes in the network... | ||
1387 | + node.classed('selected', false); | ||
1388 | + selections = {}; | ||
1389 | + selectOrder = []; | ||
1390 | + updateDeviceColors(); | ||
1391 | + updateDetailPanel(); | ||
1392 | + } | ||
1393 | + | ||
1326 | // ========================== | 1394 | // ========================== |
1327 | // === MOUSE GESTURE HANDLERS | 1395 | // === MOUSE GESTURE HANDLERS |
1328 | 1396 | ||
1329 | - function selectCb(d) { | 1397 | + function zoomingOrPanning(ev) { |
1330 | - // this is the selected node | 1398 | + return ev.metaKey || ev.altKey; |
1331 | - $log.debug("\n\n\nSelect Object: "); | ||
1332 | - $log.debug("d is ", d); | ||
1333 | - $log.debug("this is ", this); | ||
1334 | - $log.debug('\n\n'); | ||
1335 | } | 1399 | } |
1336 | 1400 | ||
1337 | function atDragEnd(d) { | 1401 | function atDragEnd(d) { |
... | @@ -1345,8 +1409,7 @@ | ... | @@ -1345,8 +1409,7 @@ |
1345 | function dragEnabled() { | 1409 | function dragEnabled() { |
1346 | var ev = d3.event.sourceEvent; | 1410 | var ev = d3.event.sourceEvent; |
1347 | // nodeLock means we aren't allowing nodes to be dragged... | 1411 | // nodeLock means we aren't allowing nodes to be dragged... |
1348 | - // meta or alt key pressed means we are zooming/panning... | 1412 | + return !nodeLock && !zoomingOrPanning(ev); |
1349 | - return !nodeLock && !(ev.metaKey || ev.altKey); | ||
1350 | } | 1413 | } |
1351 | 1414 | ||
1352 | // predicate that indicates when clicking is active | 1415 | // predicate that indicates when clicking is active |
... | @@ -1406,7 +1469,7 @@ | ... | @@ -1406,7 +1469,7 @@ |
1406 | .on('tick', tick); | 1469 | .on('tick', tick); |
1407 | 1470 | ||
1408 | drag = sus.createDragBehavior(force, | 1471 | drag = sus.createDragBehavior(force, |
1409 | - selectCb, atDragEnd, dragEnabled, clickEnabled); | 1472 | + selectObject, atDragEnd, dragEnabled, clickEnabled); |
1410 | } | 1473 | } |
1411 | 1474 | ||
1412 | function resize(dim) { | 1475 | function resize(dim) { | ... | ... |
... | @@ -201,7 +201,8 @@ describe('factory: fw/util/fn.js', function() { | ... | @@ -201,7 +201,8 @@ describe('factory: fw/util/fn.js', function() { |
201 | it('should define api functions', function () { | 201 | it('should define api functions', function () { |
202 | expect(fs.areFunctions(fs, [ | 202 | expect(fs.areFunctions(fs, [ |
203 | 'isF', 'isA', 'isS', 'isO', 'contains', | 203 | 'isF', 'isA', 'isS', 'isO', 'contains', |
204 | - 'areFunctions', 'areFunctionsNonStrict', 'windowSize', 'find' | 204 | + 'areFunctions', 'areFunctionsNonStrict', 'windowSize', 'find', |
205 | + 'inArray', 'removeFromArray' | ||
205 | ])).toBeTruthy(); | 206 | ])).toBeTruthy(); |
206 | }); | 207 | }); |
207 | 208 | ||
... | @@ -260,4 +261,68 @@ describe('factory: fw/util/fn.js', function() { | ... | @@ -260,4 +261,68 @@ describe('factory: fw/util/fn.js', function() { |
260 | it('should find Zevvv', function () { | 261 | it('should find Zevvv', function () { |
261 | expect(fs.find('Zevvv', dataset, 'name')).toEqual(4); | 262 | expect(fs.find('Zevvv', dataset, 'name')).toEqual(4); |
262 | }); | 263 | }); |
264 | + | ||
265 | + | ||
266 | + // === Tests for inArray() | ||
267 | + var objRef = { x:1, y:2 }, | ||
268 | + array = [1, 3.14, 'hey', objRef, 'there', true], | ||
269 | + array2 = ['b', 'a', 'd', 'a', 's', 's']; | ||
270 | + | ||
271 | + it('should return -1 on non-arrays', function () { | ||
272 | + expect(fs.inArray(1, {x:1})).toEqual(-1); | ||
273 | + }); | ||
274 | + it('should not find HOO', function () { | ||
275 | + expect(fs.inArray('HOO', array)).toEqual(-1); | ||
276 | + }); | ||
277 | + it('should find 1', function () { | ||
278 | + expect(fs.inArray(1, array)).toEqual(0); | ||
279 | + }); | ||
280 | + it('should find pi', function () { | ||
281 | + expect(fs.inArray(3.14, array)).toEqual(1); | ||
282 | + }); | ||
283 | + it('should find hey', function () { | ||
284 | + expect(fs.inArray('hey', array)).toEqual(2); | ||
285 | + }); | ||
286 | + it('should find the object', function () { | ||
287 | + expect(fs.inArray(objRef, array)).toEqual(3); | ||
288 | + }); | ||
289 | + it('should find there', function () { | ||
290 | + expect(fs.inArray('there', array)).toEqual(4); | ||
291 | + }); | ||
292 | + it('should find true', function () { | ||
293 | + expect(fs.inArray(true, array)).toEqual(5); | ||
294 | + }); | ||
295 | + | ||
296 | + it('should find the first occurrence A', function () { | ||
297 | + expect(fs.inArray('a', array2)).toEqual(1); | ||
298 | + }); | ||
299 | + it('should find the first occurrence S', function () { | ||
300 | + expect(fs.inArray('s', array2)).toEqual(4); | ||
301 | + }); | ||
302 | + it('should not find X', function () { | ||
303 | + expect(fs.inArray('x', array2)).toEqual(-1); | ||
304 | + }); | ||
305 | + | ||
306 | + // === Tests for removeFromArray() | ||
307 | + it('should ignore non-arrays', function () { | ||
308 | + expect(fs.removeFromArray(1, {x:1})).toBe(false); | ||
309 | + }); | ||
310 | + it('should keep the array the same, for non-match', function () { | ||
311 | + var array = [1, 2, 3]; | ||
312 | + expect(fs.removeFromArray(4, array)).toBe(false); | ||
313 | + expect(array).toEqual([1, 2, 3]); | ||
314 | + }); | ||
315 | + it('should remove a value', function () { | ||
316 | + var array = [1, 2, 3]; | ||
317 | + expect(fs.removeFromArray(2, array)).toBe(true); | ||
318 | + expect(array).toEqual([1, 3]); | ||
319 | + }); | ||
320 | + it('should remove the first occurrence', function () { | ||
321 | + var array = ['x', 'y', 'z', 'z', 'y']; | ||
322 | + expect(fs.removeFromArray('y', array)).toBe(true); | ||
323 | + expect(array).toEqual(['x', 'z', 'z', 'y']); | ||
324 | + expect(fs.removeFromArray('x', array)).toBe(true); | ||
325 | + expect(array).toEqual(['z', 'z', 'y']); | ||
326 | + }); | ||
327 | + | ||
263 | }); | 328 | }); | ... | ... |
-
Please register or login to post a comment