aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js')
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js1182
1 files changed, 0 insertions, 1182 deletions
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
deleted file mode 100644
index 175ee796..00000000
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ /dev/null
@@ -1,1182 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- ONOS GUI -- Topology Force Module.
- Visualization of the topology in an SVG layer, using a D3 Force Layout.
- */
-
-(function () {
- 'use strict';
-
- // injected refs
- var $log, $timeout, fs, sus, ts, flash, wss, tov,
- tis, tms, td3, tss, tts, tos, fltr, tls, uplink, svg;
-
- // configuration
- var linkConfig = {
- light: {
- baseColor: '#666',
- inColor: '#66f',
- outColor: '#f00'
- },
- dark: {
- baseColor: '#aaa',
- inColor: '#66f',
- outColor: '#f66'
- },
- inWidth: 12,
- outWidth: 10
- };
-
- // internal state
- var settings, // merged default settings and options
- force, // force layout object
- drag, // drag behavior handler
- network = {
- nodes: [],
- links: [],
- linksByDevice: {},
- lookup: {},
- revLinkToKey: {}
- },
- lu, // shorthand for lookup
- rlk, // shorthand for revLinktoKey
- showHosts = false, // whether hosts are displayed
- showOffline = true, // whether offline devices are displayed
- nodeLock = false, // whether nodes can be dragged or not (locked)
- fTimer, // timer for delayed force layout
- fNodesTimer, // timer for delayed nodes update
- fLinksTimer, // timer for delayed links update
- dim, // the dimensions of the force layout [w,h]
- linkNums = []; // array of link number labels
-
- // SVG elements;
- var linkG, linkLabelG, numLinkLblsG, portLabelG, nodeG;
-
- // D3 selections;
- var link, linkLabel, node;
-
- // default settings for force layout
- var defaultSettings = {
- gravity: 0.4,
- friction: 0.7,
- charge: {
- // note: key is node.class
- device: -8000,
- host: -5000,
- _def_: -12000
- },
- linkDistance: {
- // note: key is link.type
- direct: 100,
- optical: 120,
- hostLink: 3,
- _def_: 50
- },
- linkStrength: {
- // note: key is link.type
- // range: {0.0 ... 1.0}
- //direct: 1.0,
- //optical: 1.0,
- //hostLink: 1.0,
- _def_: 1.0
- }
- };
-
-
- // ==========================
- // === EVENT HANDLERS
-
- function addDevice(data) {
- var id = data.id,
- d;
-
- uplink.showNoDevs(false);
-
- // although this is an add device event, if we already have the
- // device, treat it as an update instead..
- if (lu[id]) {
- updateDevice(data);
- return;
- }
-
- d = tms.createDeviceNode(data);
- network.nodes.push(d);
- lu[id] = d;
- updateNodes();
- fStart();
- }
-
- function updateDevice(data) {
- var id = data.id,
- d = lu[id],
- wasOnline;
-
- if (d) {
- wasOnline = d.online;
- angular.extend(d, data);
- if (tms.positionNode(d, true)) {
- sendUpdateMeta(d);
- }
- updateNodes();
- if (wasOnline !== d.online) {
- tms.findAttachedLinks(d.id).forEach(restyleLinkElement);
- updateOfflineVisibility(d);
- }
- }
- }
-
- function removeDevice(data) {
- var id = data.id,
- d = lu[id];
- if (d) {
- removeDeviceElement(d);
- }
- }
-
- function addHost(data) {
- var id = data.id,
- d, lnk;
-
- // although this is an add host event, if we already have the
- // host, treat it as an update instead..
- if (lu[id]) {
- updateHost(data);
- return;
- }
-
- d = tms.createHostNode(data);
- network.nodes.push(d);
- lu[id] = d;
- updateNodes();
-
- lnk = tms.createHostLink(data);
- if (lnk) {
- d.linkData = lnk; // cache ref on its host
- network.links.push(lnk);
- lu[d.ingress] = lnk;
- lu[d.egress] = lnk;
- updateLinks();
- }
- fStart();
- }
-
- function updateHost(data) {
- var id = data.id,
- d = lu[id];
- if (d) {
- angular.extend(d, data);
- if (tms.positionNode(d, true)) {
- sendUpdateMeta(d);
- }
- updateNodes();
- }
- }
-
- function moveHost(data) {
- var id = data.id,
- d = lu[id],
- lnk;
- if (d) {
- // first remove the old host link
- removeLinkElement(d.linkData);
-
- // merge new data
- angular.extend(d, data);
- if (tms.positionNode(d, true)) {
- sendUpdateMeta(d);
- }
-
- // now create a new host link
- lnk = tms.createHostLink(data);
- if (lnk) {
- d.linkData = lnk;
- network.links.push(lnk);
- lu[d.ingress] = lnk;
- lu[d.egress] = lnk;
- }
-
- updateNodes();
- updateLinks();
- fResume();
- }
- }
-
- function removeHost(data) {
- var id = data.id,
- d = lu[id];
- if (d) {
- removeHostElement(d, true);
- }
- }
-
- function addLink(data) {
- var result = tms.findLink(data, 'add'),
- bad = result.badLogic,
- d = result.ldata;
-
- if (bad) {
- //logicError(bad + ': ' + link.id);
- return;
- }
-
- if (d) {
- // we already have a backing store link for src/dst nodes
- addLinkUpdate(d, data);
- return;
- }
-
- // no backing store link yet
- d = tms.createLink(data);
- if (d) {
- network.links.push(d);
- aggregateLink(d, data);
- lu[d.key] = d;
- updateLinks();
- fStart();
- }
- }
-
- function updateLink(data) {
- var result = tms.findLink(data, 'update'),
- bad = result.badLogic;
- if (bad) {
- //logicError(bad + ': ' + link.id);
- return;
- }
- result.updateWith(link);
- }
-
- function removeLink(data) {
- var result = tms.findLink(data, 'remove');
-
- if (!result.badLogic) {
- result.removeRawLink();
- }
- }
-
- function topoStartDone(data) {
- // called when the initial barrage of data has been sent from server
- uplink.topoStartDone();
- }
-
- // ========================
-
- function nodeById(id) {
- return lu[id];
- }
-
- function makeNodeKey(node1, node2) {
- return node1 + '-' + node2;
- }
-
- function findNodePair(key, keyRev) {
- if (network.linksByDevice[key]) {
- return key;
- } else if (network.linksByDevice[keyRev]) {
- return keyRev;
- } else {
- return false;
- }
- }
-
- function aggregateLink(ldata, link) {
- var key = makeNodeKey(link.src, link.dst),
- keyRev = makeNodeKey(link.dst, link.src),
- found = findNodePair(key, keyRev);
-
- if (found) {
- network.linksByDevice[found].push(ldata);
- ldata.devicePair = found;
- } else {
- network.linksByDevice[key] = [ ldata ];
- ldata.devicePair = key;
- }
- }
-
- function addLinkUpdate(ldata, link) {
- // add link event, but we already have the reverse link installed
- ldata.fromTarget = link;
- rlk[link.id] = ldata.key;
- // possible solution to el being undefined in restyleLinkElement:
- //_updateLinks();
- restyleLinkElement(ldata);
- }
-
-
- var widthRatio = 1.4,
- linkScale = d3.scale.linear()
- .domain([1, 12])
- .range([widthRatio, 12 * widthRatio])
- .clamp(true),
- allLinkTypes = 'direct indirect optical tunnel';
-
- function restyleLinkElement(ldata, immediate) {
- // this fn's job is to look at raw links and decide what svg classes
- // need to be applied to the line element in the DOM
- var th = ts.theme(),
- el = ldata.el,
- type = ldata.type(),
- lw = ldata.linkWidth(),
- online = ldata.online(),
- delay = immediate ? 0 : 1000;
-
- // FIXME: understand why el is sometimes undefined on addLink events...
- // Investigated:
- // el is undefined when it's a reverse link that is being added.
- // updateLinks (which sets ldata.el) isn't called before this is called.
- // Calling _updateLinks in addLinkUpdate fixes it, but there might be
- // a more efficient way to fix it.
- if (el && !el.empty()) {
- el.classed('link', true);
- el.classed('inactive', !online);
- el.classed(allLinkTypes, false);
- if (type) {
- el.classed(type, true);
- }
- el.transition()
- .duration(delay)
- .attr('stroke-width', linkScale(lw))
- .attr('stroke', linkConfig[th].baseColor);
- }
- }
-
- function removeLinkElement(d) {
- var idx = fs.find(d.key, network.links, 'key'),
- removed;
- if (idx >=0) {
- // remove from links array
- removed = network.links.splice(idx, 1);
- // remove from lookup cache
- delete lu[removed[0].key];
- updateLinks();
- fResume();
- }
- }
-
- function removeHostElement(d, upd) {
- // first, remove associated hostLink...
- removeLinkElement(d.linkData);
-
- // remove hostLink bindings
- delete lu[d.ingress];
- delete lu[d.egress];
-
- // remove from lookup cache
- delete lu[d.id];
- // remove from nodes array
- var idx = fs.find(d.id, network.nodes);
- network.nodes.splice(idx, 1);
-
- // remove from SVG
- // NOTE: upd is false if we were called from removeDeviceElement()
- if (upd) {
- updateNodes();
- fResume();
- }
- }
-
- function removeDeviceElement(d) {
- var id = d.id,
- idx;
- // first, remove associated hosts and links..
- tms.findAttachedHosts(id).forEach(removeHostElement);
- tms.findAttachedLinks(id).forEach(removeLinkElement);
-
- // remove from lookup cache
- delete lu[id];
- // remove from nodes array
- idx = fs.find(id, network.nodes);
- if (idx > -1) {
- network.nodes.splice(idx, 1);
- }
-
- if (!network.nodes.length) {
- uplink.showNoDevs(true);
- }
-
- // remove from SVG
- updateNodes();
- fResume();
- }
-
- function updateHostVisibility() {
- sus.visible(nodeG.selectAll('.host'), showHosts);
- sus.visible(linkG.selectAll('.hostLink'), showHosts);
- sus.visible(linkLabelG.selectAll('.hostLinkLabel'), showHosts);
- }
-
- function updateOfflineVisibility(dev) {
- function updDev(d, show) {
- var b;
- sus.visible(d.el, show);
-
- tms.findAttachedLinks(d.id).forEach(function (link) {
- b = show && ((link.type() !== 'hostLink') || showHosts);
- sus.visible(link.el, b);
- });
- tms.findAttachedHosts(d.id).forEach(function (host) {
- b = show && showHosts;
- sus.visible(host.el, b);
- });
- }
-
- if (dev) {
- // updating a specific device that just toggled off/on-line
- updDev(dev, dev.online || showOffline);
- } else {
- // updating all offline devices
- tms.findDevices(true).forEach(function (d) {
- updDev(d, showOffline);
- });
- }
- }
-
-
- function sendUpdateMeta(d, clearPos) {
- var metaUi = {},
- ll;
-
- // if we are not clearing the position data (unpinning),
- // attach the x, y, longitude, latitude...
- if (!clearPos) {
- ll = tms.lngLatFromCoord([d.x, d.y]);
- metaUi = {x: d.x, y: d.y, lng: ll[0], lat: ll[1]};
- }
- d.metaUi = metaUi;
- wss.sendEvent('updateMeta', {
- id: d.id,
- class: d.class,
- memento: metaUi
- });
- }
-
-
- function mkSvgClass(d) {
- return d.fixed ? d.svgClass + ' fixed' : d.svgClass;
- }
-
- function vis(b) {
- return b ? 'visible' : 'hidden';
- }
-
- function toggleHosts(x) {
- var kev = (x === 'keyev'),
- on = kev ? !showHosts : !!x;
-
- showHosts = on;
- updateHostVisibility();
- flash.flash('Hosts ' + vis(on));
- return on;
- }
-
- function toggleOffline(x) {
- var kev = (x === 'keyev'),
- on = kev ? !showOffline : !!x;
-
- showOffline = on;
- updateOfflineVisibility();
- flash.flash('Offline devices ' + vis(on));
- return on;
- }
-
- function cycleDeviceLabels() {
- flash.flash(td3.incDevLabIndex());
- tms.findDevices().forEach(function (d) {
- td3.updateDeviceLabel(d);
- });
- }
-
- function unpin() {
- var hov = tss.hovered();
- if (hov) {
- sendUpdateMeta(hov, true);
- hov.fixed = false;
- hov.el.classed('fixed', false);
- fResume();
- }
- }
-
- function showMastership(masterId) {
- if (!masterId) {
- restoreLayerState();
- } else {
- showMastershipFor(masterId);
- }
- }
-
- function restoreLayerState() {
- // NOTE: this level of indirection required, for when we have
- // the layer filter functionality re-implemented
- suppressLayers(false);
- }
-
- function showMastershipFor(id) {
- suppressLayers(true);
- node.each(function (n) {
- if (n.master === id) {
- n.el.classed('suppressedmax', false);
- }
- });
- }
-
- function supAmt(less) {
- return less ? "suppressed" : "suppressedmax";
- }
-
- function suppressLayers(b, less) {
- var cls = supAmt(less);
- node.classed(cls, b);
- link.classed(cls, b);
- }
-
- function unsuppressNode(id, less) {
- var cls = supAmt(less);
- node.each(function (n) {
- if (n.id === id) {
- n.el.classed(cls, false);
- }
- });
- }
-
- function unsuppressLink(key, less) {
- var cls = supAmt(less);
- link.each(function (n) {
- if (n.key === key) {
- n.el.classed(cls, false);
- }
- });
- }
-
- function showBadLinks() {
- var badLinks = tms.findBadLinks();
- flash.flash('Bad Links: ' + badLinks.length);
- $log.debug('Bad Link List (' + badLinks.length + '):');
- badLinks.forEach(function (d) {
- $log.debug('bad link: (' + d.bad + ') ' + d.key, d);
- if (d.el) {
- d.el.attr('stroke-width', linkScale(2.8))
- .attr('stroke', 'red');
- }
- });
- // back to normal after 2 seconds...
- $timeout(updateLinks, 2000);
- }
-
- // ==========================================
-
- function updateNodes() {
- if (fNodesTimer) {
- $timeout.cancel(fNodesTimer);
- }
- fNodesTimer = $timeout(_updateNodes, 150);
- }
-
- // IMPLEMENTATION NOTE: _updateNodes() should NOT stop, start, or resume
- // the force layout; that needs to be determined and implemented elsewhere
- function _updateNodes() {
- // select all the nodes in the layout:
- node = nodeG.selectAll('.node')
- .data(network.nodes, function (d) { return d.id; });
-
- // operate on existing nodes:
- node.filter('.device').each(td3.deviceExisting);
- node.filter('.host').each(td3.hostExisting);
-
- // operate on entering nodes:
- var entering = node.enter()
- .append('g')
- .attr({
- id: function (d) { return sus.safeId(d.id); },
- class: mkSvgClass,
- transform: function (d) {
- // Need to guard against NaN here ??
- return sus.translate(d.x, d.y);
- },
- opacity: 0
- })
- .call(drag)
- .on('mouseover', tss.nodeMouseOver)
- .on('mouseout', tss.nodeMouseOut)
- .transition()
- .attr('opacity', 1);
-
- // augment entering nodes:
- entering.filter('.device').each(td3.deviceEnter);
- entering.filter('.host').each(td3.hostEnter);
-
- // operate on both existing and new nodes:
- td3.updateDeviceColors();
-
- // operate on exiting nodes:
- // Note that the node is removed after 2 seconds.
- // Sub element animations should be shorter than 2 seconds.
- var exiting = node.exit()
- .transition()
- .duration(2000)
- .style('opacity', 0)
- .remove();
-
- // exiting node specifics:
- exiting.filter('.host').each(td3.hostExit);
- exiting.filter('.device').each(td3.deviceExit);
- }
-
- // ==========================
-
- function getDefaultPos(link) {
- return {
- x1: link.source.x,
- y1: link.source.y,
- x2: link.target.x,
- y2: link.target.y
- };
- }
-
- // returns amount of adjustment along the normal for given link
- function amt(numLinks, linkIdx) {
- var gap = 6;
- return (linkIdx - ((numLinks - 1) / 2)) * gap;
- }
-
- function calcMovement(d, amt, flipped) {
- var pos = getDefaultPos(d),
- mult = flipped ? -amt : amt,
- dx = pos.x2 - pos.x1,
- dy = pos.y2 - pos.y1,
- length = Math.sqrt((dx * dx) + (dy * dy));
-
- return {
- x1: pos.x1 + (mult * dy / length),
- y1: pos.y1 + (mult * -dx / length),
- x2: pos.x2 + (mult * dy / length),
- y2: pos.y2 + (mult * -dx / length)
- };
- }
-
- function calcPosition() {
- var lines = this,
- linkSrcId;
- linkNums = [];
- lines.each(function (d) {
- if (d.type() === 'hostLink') {
- d.position = getDefaultPos(d);
- }
- });
-
- function normalizeLinkSrc(link) {
- // ensure source device is consistent across set of links
- // temporary measure until link modeling is refactored
- if (!linkSrcId) {
- linkSrcId = link.source.id;
- return false;
- }
-
- return link.source.id !== linkSrcId;
- }
-
- angular.forEach(network.linksByDevice, function (linkArr, key) {
- var numLinks = linkArr.length,
- link;
-
- if (numLinks === 1) {
- link = linkArr[0];
- link.position = getDefaultPos(link);
- link.position.multiLink = false;
- } else if (numLinks >= 5) {
- // this code is inefficient, in the future the way links
- // are modeled will be changed
- angular.forEach(linkArr, function (link) {
- link.position = getDefaultPos(link);
- link.position.multiLink = true;
- });
- linkNums.push({
- id: key,
- num: numLinks,
- linkCoords: linkArr[0].position
- });
- } else {
- linkSrcId = null;
- angular.forEach(linkArr, function (link, index) {
- var offsetAmt = amt(numLinks, index),
- needToFlip = normalizeLinkSrc(link);
- link.position = calcMovement(link, offsetAmt, needToFlip);
- link.position.multiLink = false;
- });
- }
- });
- }
-
- function updateLinks() {
- if (fLinksTimer) {
- $timeout.cancel(fLinksTimer);
- }
- fLinksTimer = $timeout(_updateLinks, 150);
- }
-
- // IMPLEMENTATION NOTE: _updateLinks() should NOT stop, start, or resume
- // the force layout; that needs to be determined and implemented elsewhere
- function _updateLinks() {
- var th = ts.theme();
-
- link = linkG.selectAll('.link')
- .data(network.links, function (d) { return d.key; });
-
- // operate on existing links:
- link.each(function (d) {
- // this is supposed to be an existing link, but we have observed
- // occasions (where links are deleted and added rapidly?) where
- // the DOM element has not been defined. So protect against that...
- if (d.el) {
- restyleLinkElement(d, true);
- }
- });
-
- // operate on entering links:
- var entering = link.enter()
- .append('line')
- .call(calcPosition)
- .attr({
- x1: function (d) { return d.position.x1; },
- y1: function (d) { return d.position.y1; },
- x2: function (d) { return d.position.x2; },
- y2: function (d) { return d.position.y2; },
- stroke: linkConfig[th].inColor,
- 'stroke-width': linkConfig.inWidth
- });
-
- // augment links
- entering.each(td3.linkEntering);
-
- // operate on both existing and new links:
- //link.each(...)
-
- // add labels for how many links are in a thick line
- td3.applyNumLinkLabels(linkNums, numLinkLblsG);
-
- // apply or remove labels
- td3.applyLinkLabels();
-
- // operate on exiting links:
- link.exit()
- .attr('stroke-dasharray', '3 3')
- .attr('stroke', linkConfig[th].outColor)
- .style('opacity', 0.5)
- .transition()
- .duration(1500)
- .attr({
- 'stroke-dasharray': '3 12',
- 'stroke-width': linkConfig.outWidth
- })
- .style('opacity', 0.0)
- .remove();
- }
-
-
- // ==========================
- // force layout tick function
-
- function fResume() {
- if (!tos.isOblique()) {
- force.resume();
- }
- }
-
- function fStart() {
- if (!tos.isOblique()) {
- if (fTimer) {
- $timeout.cancel(fTimer);
- }
- fTimer = $timeout(function () {
- $log.debug("Starting force-layout");
- force.start();
- }, 200);
- }
- }
-
- var tickStuff = {
- nodeAttr: {
- transform: function (d) {
- var dx = isNaN(d.x) ? 0 : d.x,
- dy = isNaN(d.y) ? 0 : d.y;
- return sus.translate(dx, dy);
- }
- },
- linkAttr: {
- x1: function (d) { return d.position.x1; },
- y1: function (d) { return d.position.y1; },
- x2: function (d) { return d.position.x2; },
- y2: function (d) { return d.position.y2; }
- },
- linkLabelAttr: {
- transform: function (d) {
- var lnk = tms.findLinkById(d.key);
- if (lnk) {
- return td3.transformLabel(lnk.position);
- }
- }
- }
- };
-
- function tick() {
- // guard against null (which can happen when our view pages out)...
- if (node && node.size()) {
- node.attr(tickStuff.nodeAttr);
- }
- if (link && link.size()) {
- link.call(calcPosition)
- .attr(tickStuff.linkAttr);
- td3.applyNumLinkLabels(linkNums, numLinkLblsG);
- }
- if (linkLabel && linkLabel.size()) {
- linkLabel.attr(tickStuff.linkLabelAttr);
- }
- }
-
-
- // ==========================
- // === MOUSE GESTURE HANDLERS
-
- function zoomingOrPanning(ev) {
- return ev.metaKey || ev.altKey;
- }
-
- function atDragEnd(d) {
- // once we've finished moving, pin the node in position
- d.fixed = true;
- d3.select(this).classed('fixed', true);
- sendUpdateMeta(d);
- tss.clickConsumed(true);
- }
-
- // predicate that indicates when dragging is active
- function dragEnabled() {
- var ev = d3.event.sourceEvent;
- // nodeLock means we aren't allowing nodes to be dragged...
- return !nodeLock && !zoomingOrPanning(ev);
- }
-
- // predicate that indicates when clicking is active
- function clickEnabled() {
- return true;
- }
-
- // =============================================
- // function entry points for overlay module
-
- // TODO: find an automatic way of tracking via the "showHighlights" events
- var allTrafficClasses = 'primary secondary optical animated ' +
- 'port-traffic-Kbps port-traffic-Mbps port-traffic-Gbps ' +
- 'port-traffic-Gbps-choked';
-
- function clearLinkTrafficStyle() {
- link.style('stroke-width', null)
- .classed(allTrafficClasses, false);
- }
-
- function removeLinkLabels() {
- network.links.forEach(function (d) {
- d.label = '';
- });
- }
-
- function clearNodeDeco() {
- node.selectAll('g.badge').remove();
- }
-
- function removeNodeBadges() {
- network.nodes.forEach(function (d) {
- d.badge = null;
- });
- }
-
- function updateLinkLabelModel() {
- // create the backing data for showing labels..
- var data = [];
- link.each(function (d) {
- if (d.label) {
- data.push({
- id: 'lab-' + d.key,
- key: d.key,
- label: d.label,
- ldata: d
- });
- }
- });
-
- linkLabel = linkLabelG.selectAll('.linkLabel')
- .data(data, function (d) { return d.id; });
- }
-
- // ==========================
- // Module definition
-
- function mkModelApi(uplink) {
- return {
- projection: uplink.projection,
- network: network,
- restyleLinkElement: restyleLinkElement,
- removeLinkElement: removeLinkElement
- };
- }
-
- function mkD3Api() {
- return {
- node: function () { return node; },
- link: function () { return link; },
- linkLabel: function () { return linkLabel; },
- instVisible: function () { return tis.isVisible(); },
- posNode: tms.positionNode,
- showHosts: function () { return showHosts; },
- restyleLinkElement: restyleLinkElement,
- updateLinkLabelModel: updateLinkLabelModel,
- linkConfig: function () { return linkConfig; }
- };
- }
-
- function mkSelectApi() {
- return {
- node: function () { return node; },
- zoomingOrPanning: zoomingOrPanning,
- updateDeviceColors: td3.updateDeviceColors,
- deselectLink: tls.deselectLink
- };
- }
-
- function mkTrafficApi() {
- return {
- hovered: tss.hovered,
- somethingSelected: tss.somethingSelected,
- selectOrder: tss.selectOrder
- };
- }
-
- function mkOverlayApi() {
- return {
- clearNodeDeco: clearNodeDeco,
- removeNodeBadges: removeNodeBadges,
- clearLinkTrafficStyle: clearLinkTrafficStyle,
- removeLinkLabels: removeLinkLabels,
- findLinkById: tms.findLinkById,
- findNodeById: nodeById,
- updateLinks: updateLinks,
- updateNodes: updateNodes,
- supLayers: suppressLayers,
- unsupNode: unsuppressNode,
- unsupLink: unsuppressLink
- };
- }
-
- function mkObliqueApi(uplink, fltr) {
- return {
- force: function() { return force; },
- zoomLayer: uplink.zoomLayer,
- nodeGBBox: function() { return nodeG.node().getBBox(); },
- node: function () { return node; },
- link: function () { return link; },
- linkLabel: function () { return linkLabel; },
- nodes: function () { return network.nodes; },
- tickStuff: tickStuff,
- nodeLock: function (b) {
- var old = nodeLock;
- nodeLock = b;
- return old;
- },
- opacifyMap: uplink.opacifyMap,
- inLayer: fltr.inLayer,
- calcLinkPos: calcPosition,
- applyNumLinkLabels: function () {
- td3.applyNumLinkLabels(linkNums, numLinkLblsG);
- }
- };
- }
-
- function mkFilterApi() {
- return {
- node: function () { return node; },
- link: function () { return link; }
- };
- }
-
- function mkLinkApi(svg, uplink) {
- return {
- svg: svg,
- zoomer: uplink.zoomer(),
- network: network,
- portLabelG: function () { return portLabelG; },
- showHosts: function () { return showHosts; }
- };
- }
-
- angular.module('ovTopo')
- .factory('TopoForceService',
- ['$log', '$timeout', 'FnService', 'SvgUtilService',
- 'ThemeService', 'FlashService', 'WebSocketService',
- 'TopoOverlayService', 'TopoInstService', 'TopoModelService',
- 'TopoD3Service', 'TopoSelectService', 'TopoTrafficService',
- 'TopoObliqueService', 'TopoFilterService', 'TopoLinkService',
-
- function (_$log_, _$timeout_, _fs_, _sus_, _ts_, _flash_, _wss_, _tov_,
- _tis_, _tms_, _td3_, _tss_, _tts_, _tos_, _fltr_, _tls_) {
- $log = _$log_;
- $timeout = _$timeout_;
- fs = _fs_;
- sus = _sus_;
- ts = _ts_;
- flash = _flash_;
- wss = _wss_;
- tov = _tov_;
- tis = _tis_;
- tms = _tms_;
- td3 = _td3_;
- tss = _tss_;
- tts = _tts_;
- tos = _tos_;
- fltr = _fltr_;
- tls = _tls_;
-
- var themeListener = ts.addListener(function () {
- updateLinks();
- updateNodes();
- });
-
- // forceG is the SVG group to display the force layout in
- // uplink is the api from the main topo source file
- // dim is the initial dimensions of the SVG as [w,h]
- // opts are, well, optional :)
- function initForce(_svg_, forceG, _uplink_, _dim_, opts) {
- uplink = _uplink_;
- dim = _dim_;
- svg = _svg_;
-
- lu = network.lookup;
- rlk = network.revLinkToKey;
-
- $log.debug('initForce().. dim = ' + dim);
-
- tov.setApi(mkOverlayApi(), tss);
- tms.initModel(mkModelApi(uplink), dim);
- td3.initD3(mkD3Api());
- tss.initSelect(mkSelectApi());
- tts.initTraffic(mkTrafficApi());
- tos.initOblique(mkObliqueApi(uplink, fltr));
- fltr.initFilter(mkFilterApi());
- tls.initLink(mkLinkApi(svg, uplink), td3);
-
- settings = angular.extend({}, defaultSettings, opts);
-
- linkG = forceG.append('g').attr('id', 'topo-links');
- linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels');
- numLinkLblsG = forceG.append('g').attr('id', 'topo-numLinkLabels');
- nodeG = forceG.append('g').attr('id', 'topo-nodes');
- portLabelG = forceG.append('g').attr('id', 'topo-portLabels');
-
- link = linkG.selectAll('.link');
- linkLabel = linkLabelG.selectAll('.linkLabel');
- node = nodeG.selectAll('.node');
-
- force = d3.layout.force()
- .size(dim)
- .nodes(network.nodes)
- .links(network.links)
- .gravity(settings.gravity)
- .friction(settings.friction)
- .charge(settings.charge._def_)
- .linkDistance(settings.linkDistance._def_)
- .linkStrength(settings.linkStrength._def_)
- .on('tick', tick);
-
- drag = sus.createDragBehavior(force,
- tss.selectObject, atDragEnd, dragEnabled, clickEnabled);
- }
-
- function newDim(_dim_) {
- dim = _dim_;
- force.size(dim);
- tms.newDim(dim);
- }
-
- function destroyForce() {
- force.stop();
-
- tls.destroyLink();
- tos.destroyOblique();
- tts.destroyTraffic();
- tss.destroySelect();
- td3.destroyD3();
- tms.destroyModel();
- // note: no need to destroy overlay service
- ts.removeListener(themeListener);
- themeListener = null;
-
- // clean up the DOM
- svg.selectAll('g').remove();
- svg.selectAll('defs').remove();
-
- // clean up internal state
- network.nodes = [];
- network.links = [];
- network.linksByDevice = {};
- network.lookup = {};
- network.revLinkToKey = {};
-
- linkNums = [];
-
- linkG = linkLabelG = numLinkLblsG = nodeG = portLabelG = null;
- link = linkLabel = node = null;
- force = drag = null;
-
- // clean up $timeout promises
- if (fTimer) {
- $timeout.cancel(fTimer);
- }
- if (fNodesTimer) {
- $timeout.cancel(fNodesTimer);
- }
- if (fLinksTimer) {
- $timeout.cancel(fLinksTimer);
- }
- }
-
- return {
- initForce: initForce,
- newDim: newDim,
- destroyForce: destroyForce,
-
- updateDeviceColors: td3.updateDeviceColors,
- toggleHosts: toggleHosts,
- togglePorts: tls.togglePorts,
- toggleOffline: toggleOffline,
- cycleDeviceLabels: cycleDeviceLabels,
- unpin: unpin,
- showMastership: showMastership,
- showBadLinks: showBadLinks,
-
- addDevice: addDevice,
- updateDevice: updateDevice,
- removeDevice: removeDevice,
- addHost: addHost,
- updateHost: updateHost,
- moveHost: moveHost,
- removeHost: removeHost,
- addLink: addLink,
- updateLink: updateLink,
- removeLink: removeLink,
- topoStartDone: topoStartDone
- };
- }]);
-}());