Simon Hunt
Committed by Brian O'Connor

ONOS-4359: continued work on theming UI

- topo view: device icon and label re-theming (WIP)

Change-Id: I5ecbc1c5b8a8315bfadfaacf62cfdb0e6d1f5a9c
(cherry picked from commit 92eaf445)
......@@ -149,8 +149,7 @@
// configuration for device and host icons in the topology view
var config = {
device: {
dim: 36,
rx: 4
dim: 36
},
host: {
badge: {
......@@ -170,30 +169,15 @@
};
// Adds a device icon to the specified element, using the given glyph.
// Returns the D3 selection of the icon.
function addDeviceIcon(elem, glyphId) {
var cfg = config.device,
gid = gs.glyphDefined(glyphId) ? glyphId : 'query',
g = elem.append('g')
.attr('class', 'svgIcon deviceIcon');
g.append('rect').attr({
x: 0,
y: 0,
rx: cfg.rx,
width: cfg.dim,
height: cfg.dim
});
g.append('use').attr({
// Adds a device glyph to the specified element.
// Returns the D3 selection of the glyph (use) element.
function addDeviceIcon(elem, glyphId, iconDim) {
var gid = gs.glyphDefined(glyphId) ? glyphId : 'query';
return elem.append('use').attr({
'xlink:href': '#' + gid,
width: cfg.dim,
height: cfg.dim
width: iconDim,
height: iconDim
});
g.dim = cfg.dim;
return g;
}
function addHostIcon(elem, radius, glyphId) {
......
......@@ -179,6 +179,7 @@ html[data-platform='iPad'] #topo-p-detail {
#ov-topo svg .node {
cursor: pointer;
fill-rule: evenodd;
}
#ov-topo svg .node text {
......
......@@ -39,28 +39,17 @@
*/
// configuration
var devCfg = {
xoff: -20,
yoff: -18
},
labelConfig = {
imgPad: 16,
padLR: 4,
padTB: 3,
marginLR: 3,
marginTB: 2,
port: {
gap: 3,
width: 18,
height: 14
}
},
badgeConfig = {
var devIconDim = 36;
var labelPad = 4;
var badgeConfig = {
radius: 12,
yoff: 5,
gdelta: 10
},
icfg;
};
// TODO: remove dependence on this
var icfg;
var status = {
i: 'badgeInfo',
......@@ -87,77 +76,32 @@
var deviceLabelIndex = 0,
hostLabelIndex = 0;
var dCol = {
black: '#000',
paleblue: '#acf',
offwhite: '#ddd',
darkgrey: '#444',
midgrey: '#888',
lightgrey: '#bbb',
orange: '#f90'
};
// note: these are the device icon colors without affinity
var dColTheme = {
light: {
rfill: dCol.offwhite,
online: {
glyph: dCol.darkgrey,
rect: dCol.paleblue
},
offline: {
glyph: dCol.midgrey,
rect: dCol.lightgrey
}
online: '#444444',
offline: '#cccccc'
},
dark: {
rfill: dCol.midgrey,
online: {
glyph: dCol.darkgrey,
rect: dCol.paleblue
},
offline: {
glyph: dCol.midgrey,
rect: dCol.darkgrey
}
// TODO: theme
online: '#444444',
offline: '#cccccc'
}
};
function devBaseColor(d) {
var o = d.online ? 'online' : 'offline';
return dColTheme[ts.theme()][o];
}
function setDeviceColor(d) {
function devGlyphColor(d) {
var o = d.online,
s = d.el.classed('selected'),
c = devBaseColor(d),
a = instColor(d.master, o),
icon = d.el.select('g.deviceIcon'),
g, r;
if (s) {
g = c.glyph;
r = dCol.orange;
} else if (api.instVisible()) {
g = o ? a : c.glyph;
r = o ? c.rfill : a;
} else {
g = c.glyph;
r = c.rect;
id = d.master,
otag = o ? 'online' : 'offline';
return o ? sus.cat7().getColor(id, 0, ts.theme())
: dColTheme[ts.theme()][otag];
}
icon.select('use').style('fill', g);
icon.select('rect').style('fill', r);
}
function instColor(id, online) {
return sus.cat7().getColor(id, !online, ts.theme());
function setDeviceColor(d) {
d.el.select('use')
.style('fill', devGlyphColor(d));
}
// ====
function incDevLabIndex() {
setDevLabIndex(deviceLabelIndex+1);
switch(deviceLabelIndex) {
......@@ -174,82 +118,51 @@
ps.setPrefs('topo_prefs', p);
}
// Returns the newly computed bounding box of the rectangle
function adjustRectToFitText(n) {
var text = n.select('text'),
box = text.node().getBBox(),
lab = labelConfig;
text.attr('text-anchor', 'middle')
.attr('y', '-0.8em')
.attr('x', lab.imgPad/2);
// translate the bbox so that it is centered on [x,y]
box.x = -box.width / 2;
box.y = -box.height / 2;
// add padding
box.x -= (lab.padLR + lab.imgPad/2);
box.width += lab.padLR * 2 + lab.imgPad;
box.y -= lab.padTB;
box.height += lab.padTB * 2;
return box;
}
function hostLabel(d) {
var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0;
return d.labels[idx];
}
function deviceLabel(d) {
var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0;
return d.labels[idx];
}
function trimLabel(label) {
return (label && label.trim()) || '';
}
function emptyBox() {
function computeLabelWidth(n) {
var text = n.select('text'),
box = text.node().getBBox();
return box.width + labelPad * 2;
}
function iconBox(dim, labelWidth) {
return {
x: -2,
y: -2,
width: 4,
height: 4
};
x: -dim/2,
y: -dim/2,
width: dim + labelWidth,
height: dim
}
}
function updateDeviceRendering(d) {
var label = trimLabel(deviceLabel(d)),
noLabel = !label,
node = d.el,
dim = icfg.device.dim,
box, dx, dy,
bdg = d.badge;
node.select('text')
.text(label);
var node = d.el,
bdg = d.badge,
label = trimLabel(deviceLabel(d)),
labelWidth;
if (noLabel) {
box = emptyBox();
dx = -dim/2;
dy = -dim/2;
} else {
box = adjustRectToFitText(node);
dx = box.x + devCfg.xoff;
dy = box.y + devCfg.yoff;
}
node.select('text').text(label);
labelWidth = label ? computeLabelWidth(node) : 0;
node.select('rect')
.transition()
.attr(box);
.attr(iconBox(devIconDim, labelWidth));
node.select('g.deviceIcon')
.transition()
.attr('transform', sus.translate(dx, dy));
// handle badge, if defined
// TODO: verify badge placement
if (bdg) {
renderBadge(node, bdg, { dx: dx + dim, dy: dy });
renderBadge(node, bdg, { dx: devIconDim, dy: 0 });
}
}
......@@ -259,7 +172,6 @@
updateHostLabel(d);
// handle badge, if defined
if (bdg) {
renderBadge(node, bdg, icfg.host.badge);
}
......@@ -331,28 +243,26 @@
var node = d3.select(this),
glyphId = mapDeviceTypeToGlyph(d.type),
label = trimLabel(deviceLabel(d)),
noLabel = !label,
box, dx, dy, icon;
xlate = -devIconDim/2,
rect, text, glyph, labelWidth;
d.el = node;
node.append('rect').attr({ rx: 5, ry: 5 });
node.append('text').text(label).attr('dy', '1.1em');
box = adjustRectToFitText(node);
node.select('rect').attr(box);
rect = node.append('rect');
icon = is.addDeviceIcon(node, glyphId);
text = node.append('text').text(label)
.attr('text-anchor', 'left')
.attr('y', '0.3em')
.attr('x', devIconDim / 2 + labelPad);
if (noLabel) {
dx = -icon.dim/2;
dy = -icon.dim/2;
} else {
box = adjustRectToFitText(node);
dx = box.x + devCfg.xoff;
dy = box.y + devCfg.yoff;
}
glyph = is.addDeviceIcon(node, glyphId, devIconDim);
labelWidth = label ? computeLabelWidth(node) : 0;
rect.attr(iconBox(devIconDim, labelWidth));
glyph.attr(iconBox(devIconDim, 0));
icon.attr('transform', sus.translate(dx, dy));
node.attr('transform', sus.translate(xlate, xlate));
}
function hostEnter(d) {
......@@ -631,7 +541,6 @@
incDevLabIndex: incDevLabIndex,
setDevLabIndex: setDevLabIndex,
adjustRectToFitText: adjustRectToFitText,
hostLabel: hostLabel,
deviceLabel: deviceLabel,
trimLabel: trimLabel,
......
......@@ -29,14 +29,15 @@
// configuration
var linkConfig = {
light: {
baseColor: '#666',
baseColor: '#939598',
inColor: '#66f',
outColor: '#f00'
},
dark: {
baseColor: '#aaa',
// TODO : theme
baseColor: '#939598',
inColor: '#66f',
outColor: '#f66'
outColor: '#f00'
},
inWidth: 12,
outWidth: 10
......@@ -337,7 +338,7 @@
modeCls = ldata.expected() ? 'inactive' : 'not-permitted',
delay = immediate ? 0 : 1000;
// FIXME: understand why el is sometimes undefined on addLink events...
// NOTE: 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.
......

42.6 KB | W: | H:

42.9 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin

668 Bytes | W: | H:

665 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
{
"event": "updateInstance",
"payload": {
"id": "192.168.56.101",
"ip": "192.168.56.101",
"online": true,
"ready": true,
"uiAttached": true,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-2",
"ip": "192.168.56.102",
"online": true,
"ready": true,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-3",
"ip": "192.168.56.103",
"online": true,
"ready": true,
"uiAttached": false,
"switches": 0
}
}
{
"event": "addDevice",
"payload": {
"id": "of:0000ffffffff000a",
"type": "switch",
"online": false,
"master": "192.168.56.101",
"x-location": {
"type": "lnglat",
"lat": 37.7833,
"lng": -122.4167
},
"labels": [
"",
"sw-A",
"0000ffffffff000a"
],
"metaUi": {
"x": 520,
"y": 350
}
}
}
{
"event": "addDevice",
"payload": {
"id": "of:0000ffffffff000b",
"type": "switch",
"online": false,
"master": "ONOS-2",
"x-location": {
"type": "lnglat",
"lat": 37.7833,
"lng": -120.4167
},
"labels": [
"",
"sw-B",
"0000ffffffff000b"
],
"metaUi": {
"x": 720,
"y": 300
}
}
}
{
"event": "addDevice",
"payload": {
"id": "of:0000ffffffff000c",
"type": "switch",
"online": false,
"master": "ONOS-3",
"x-location": {
"type": "lnglat",
"lat": 37.7833,
"lng": -118.4167
},
"labels": [
"",
"sw-C",
"0000ffffffff000c"
],
"metaUi": {
"x": 920,
"y": 360
}
}
}
{
"event": "addDevice",
"payload": {
"id": "of:0000ffffffff000a",
"type": "switch",
"online": true,
"master": "192.168.56.101",
"x-location": {
"type": "lnglat",
"lat": 37.7833,
"lng": -122.4167
},
"labels": [
"",
"sw-A",
"0000ffffffff000a"
],
"metaUi": {
"x": 520,
"y": 350
}
}
}
{
"event": "addDevice",
"payload": {
"id": "of:0000ffffffff000b",
"type": "switch",
"online": true,
"master": "ONOS-2",
"x-location": {
"type": "lnglat",
"lat": 37.7833,
"lng": -120.4167
},
"labels": [
"",
"sw-B",
"0000ffffffff000b"
],
"metaUi": {
"x": 720,
"y": 300
}
}
}
{
"event": "addDevice",
"payload": {
"id": "of:0000ffffffff000c",
"type": "switch",
"online": true,
"master": "ONOS-3",
"x-location": {
"type": "lnglat",
"lat": 37.7833,
"lng": -118.4167
},
"labels": [
"",
"sw-C",
"0000ffffffff000c"
],
"metaUi": {
"x": 920,
"y": 360
}
}
}
{
"event": "addLink",
"payload": {
"id": "of:0000ffffffff000a/11-of:0000ffffffff000b/10",
"type": "direct",
"online": true,
"linkWidth": 2,
"src": "of:0000ffffffff000a",
"srcPort": "11",
"dst": "of:0000ffffffff000b",
"dstPort": "10"
}
}
{
"event": "addLink",
"payload": {
"id": "of:0000ffffffff000b/10-of:0000ffffffff000a/11",
"type": "direct",
"online": true,
"linkWidth": 2,
"src": "of:0000ffffffff000b",
"srcPort": "10",
"dst": "of:0000ffffffff000a",
"dstPort": "11"
}
}
{
"event": "addLink",
"payload": {
"id": "of:0000ffffffff000a/12-of:0000ffffffff000c/10",
"type": "direct",
"online": true,
"linkWidth": 2,
"src": "of:0000ffffffff000a",
"srcPort": "12",
"dst": "of:0000ffffffff000c",
"dstPort": "10"
}
}
{
"event": "addLink",
"payload": {
"id": "of:0000ffffffff000c/10-of:0000ffffffff000a/12",
"type": "direct",
"online": true,
"linkWidth": 2,
"src": "of:0000ffffffff000c",
"srcPort": "10",
"dst": "of:0000ffffffff000a",
"dstPort": "12"
}
}
{
"event": "addLink",
"payload": {
"id": "of:0000ffffffff000b/12-of:0000ffffffff000c/11",
"type": "direct",
"online": true,
"linkWidth": 2,
"src": "of:0000ffffffff000b",
"srcPort": "12",
"dst": "of:0000ffffffff000c",
"dstPort": "11"
}
}
{
"event": "addLink",
"payload": {
"id": "of:0000ffffffff000c/11-of:0000ffffffff000b/12",
"type": "direct",
"online": true,
"linkWidth": 2,
"src": "of:0000ffffffff000c",
"srcPort": "11",
"dst": "of:0000ffffffff000b",
"dstPort": "12"
}
}
{
"event": "addHost",
"payload": {
"id": "0E:2A:69:30:13:86/-1",
"ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff000a/2",
"egress": "of:0000ffffffff000a/2-0E:2A:69:30:13:86/-1/0",
"cp": {
"device": "of:0000ffffffff000a",
"port": 2
},
"labels": [
"192.168.222.10",
"0E:2A:69:30:13:86"
],
"metaUi": {
"Xx": 800,
"Xy": 180
}
}
}
{
"event": "addHost",
"payload": {
"id": "0E:2A:69:30:13:87/-1",
"ingress": "0E:2A:69:30:13:87/-1/0-of:0000ffffffff000b/2",
"egress": "of:0000ffffffff000b/2-0E:2A:69:30:13:87/-1/0",
"cp": {
"device": "of:0000ffffffff000b",
"port": 2
},
"labels": [
"192.168.222.11",
"0E:2A:69:30:13:87"
],
"metaUi": {
"Xx": 800,
"Xy": 180
}
}
}
{
"event": "addHost",
"payload": {
"id": "0E:2A:69:30:13:88/-1",
"ingress": "0E:2A:69:30:13:88/-1/0-of:0000ffffffff000c/2",
"egress": "of:0000ffffffff000c/2-0E:2A:69:30:13:88/-1/0",
"cp": {
"device": "of:0000ffffffff000c",
"port": 2
},
"labels": [
"192.168.222.12",
"0E:2A:69:30:13:88"
],
"metaUi": {
"Xx": 800,
"Xy": 180
}
}
}
......@@ -4,7 +4,7 @@
],
"title": "Color-Tweaking Scenario for Mojo Palette",
"params": {
"lastAuto": 7
"lastAuto": 19
},
"description": [
"Press 'a' to load initial events.",
......