Bri Prebilic Cole

ONOS-2328 GUI -- Enhanced Topology View to show multiple links individually betw…

…een devices (1 - 4). 5 or more is a thick line.

Change-Id: Ie096086454fd8d1d5d40f09396681f9cba8597a1
......@@ -367,17 +367,10 @@
.classed('linkLabel', true)
.attr('id', function (d) { return d.id; });
// FIXME: x and y position calculated here, use link.position obj
entering.each(function (d) {
var el = d3.select(this),
rect,
text,
parms = {
x1: d.ldata.source.x,
y1: d.ldata.source.y,
x2: d.ldata.target.x,
y2: d.ldata.target.y
};
text;
if (d.ldata.type() === 'hostLink') {
el.classed('hostLinkLabel', true);
......@@ -390,7 +383,7 @@
rect.attr(rectAroundText(el));
text.attr('dy', linkLabelOffset);
el.attr('transform', transformLabel(parms));
el.attr('transform', transformLabel(d.ldata.position));
});
// Remove any labels that are no longer required.
......@@ -411,7 +404,6 @@
return box;
}
// FIXME: x and y position calculated here
function transformLabel(p) {
var dx = p.x2 - p.x1,
dy = p.y2 - p.y1,
......
......@@ -575,6 +575,82 @@
// ==========================
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;
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) {
var numLinks = linkArr.length,
link;
if (numLinks === 1) {
link = linkArr[0];
link.position = getDefaultPos(link);
} 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;
});
} else {
// calculate position of links
linkSrcId = null;
angular.forEach(linkArr, function (link, index) {
var offsetAmt = amt(numLinks, index),
needToFlip = normalizeLinkSrc(link);
link.position = calcMovement(link, offsetAmt, needToFlip);
});
}
});
}
function updateLinks() {
if (fLinksTimer) {
$timeout.cancel(fLinksTimer);
......@@ -602,14 +678,14 @@
});
// operate on entering links:
// FIXME: x and y position calculated here - calculate position and add it to the link
var entering = link.enter()
.append('line')
.call(calcPosition)
.attr({
x1: function (d) { return d.source.x; },
y1: function (d) { return d.source.y; },
x2: function (d) { return d.target.x; },
y2: function (d) { return d.target.y; },
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
});
......@@ -664,24 +740,17 @@
nodeAttr: {
transform: function (d) { return sus.translate(d.x, d.y); }
},
// FIXME: x and y position calculated here, will be deleted
linkAttr: {
x1: function (d) { return d.source.x; },
y1: function (d) { return d.source.y; },
x2: function (d) { return d.target.x; },
y2: function (d) { return d.target.y; }
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) {
// FIXME: x and y position calculated here, use link.position object
return td3.transformLabel({
x1: lnk.source.x,
y1: lnk.source.y,
x2: lnk.target.x,
y2: lnk.target.y
});
return td3.transformLabel(lnk.position);
}
}
}
......@@ -693,8 +762,8 @@
node.attr(tickStuff.nodeAttr);
}
if (link) {
// FIXME: instead of tickStuff here, use link.position object
link.attr(tickStuff.linkAttr);
link.call(calcPosition)
.attr(tickStuff.linkAttr);
}
if (linkLabel) {
linkLabel.attr(tickStuff.linkLabelAttr);
......@@ -827,7 +896,8 @@
return old;
},
opacifyMap: uplink.opacifyMap,
inLayer: fltr.inLayer
inLayer: fltr.inLayer,
calcLinkPos: calcPosition
};
}
......
......@@ -104,16 +104,6 @@
return {x:x4, y:y4};
}
// FIXME: x and y position calculated here, use link.position
function lineSeg(d) {
return {
x1: d.source.x,
y1: d.source.y,
x2: d.target.x,
y2: d.target.y
};
}
function lineHit(line, p, m) {
if (p.x < line.x1 && p.x < line.x2) return false;
if (p.x > line.x1 && p.x > line.x2) return false;
......@@ -131,7 +121,7 @@
return; // skip hidden host links
}
var line = lineSeg(d),
var line = d.position,
point = pdrop(line, mouse),
hit = lineHit(line, point, mouse),
dist;
......@@ -201,24 +191,23 @@
td3.applyPortLabels(data, api.portLabelG());
}
// FIXME: x and y position calculated here somewhere
function locatePortLabel(link, src) {
var near = src ? 'source' : 'target',
far = src ? 'target' : 'source',
ln = link[near],
lf = link[far],
offset = 32;
var offset = 32,
pos = link.position,
nearX = src ? pos.x1 : pos.x2,
nearY = src ? pos.y1 : pos.y2,
farX = src ? pos.x2 : pos.x1,
farY = src ? pos.y2 : pos.y1;
function dist(x, y) { return Math.sqrt(x*x + y*y); }
var dx = lf.x - ln.x,
dy = lf.y - ln.y,
var dx = farX - nearX,
dy = farY - nearY,
k = offset / dist(dx, dy);
return {x: k * dx + ln.x, y: k * dy + ln.y};
return {x: k * dx + nearX, y: k * dy + nearY};
}
function selectLink(ldata) {
// if the new link is same as old link, do nothing
if (selectedLink && ldata && selectedLink.key === ldata.key) return;
......
......@@ -209,7 +209,7 @@
t = lnk.fromTarget,
ws = (s && s.linkWidth) || 0,
wt = (t && t.linkWidth) || 0;
return Math.max(ws, wt);
return lnk.position.multiLink ? 5 : Math.max(ws, wt);
}
});
return lnk;
......
......@@ -39,6 +39,7 @@
nodeLock(b) // test-and-set nodeLock state
opacifyMap(b) // show or hide map layer
inLayer(d, layer) // return true if d in layer {'pkt'|'opt'}
calcLinkPos() // recomputes link pos based on node data
*/
// configuration
......@@ -155,6 +156,7 @@
.attr(api.tickStuff.nodeAttr);
api.link().transition()
.duration(time)
.call(api.calcLinkPos)
.attr(api.tickStuff.linkAttr);
api.linkLabel().transition()
.duration(time)
......