Topo2: Reset node position and unpin
Refactored NodeModel
Added class to the surrounding rect for selected class
Renamed Panels to avoid conflict with classic topo
Topo2: Details Panel for single device selection
Topo2: Added Equalize Masters keyboard shortcut
Topo2: Toggle Link Port highlighting
Topo2: Node Labels was returning empty string
if friendly name was null
Topo2: Reset map zoom and panning
Change-Id: I0a949b2f8205e1abcfcac5aaec65c18d76e77cff
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
index 109a694..42275bf 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -15,18 +15,14 @@
*/
/*
- ONOS GUI -- Topology Layout Module.
- Module that contains the d3.force.layout logic
+ ONOS GUI -- Topology Node Module.
+ Module that contains model for nodes within the topology
*/
(function () {
'use strict';
- var randomService, ps, sus, is, ts, t2mcs;
- var fn;
-
- // Internal state;
- var nearDist = 15;
+ var ps, sus, is, ts, t2mcs, t2nps, fn;
var devIconDim = 36,
devIconDimMin = 20,
@@ -56,133 +52,56 @@
dColTheme[ts.theme()][otag];
}
- function positionNode(node, forUpdate) {
- var meta = node.get('metaUi'),
- x = meta && meta.x,
- y = meta && meta.y,
- dim = [800, 600],
- xy;
-
- // If the device contains explicit LONG/LAT data, use that to position
- if (setLongLat(node)) {
- // Indicate we want to update cached meta data...
- return true;
- }
-
- // else if we have [x,y] cached in meta data, use that...
- if (x !== undefined && y !== undefined) {
- node.fixed = true;
- node.px = node.x = x;
- node.py = node.y = y;
- return;
- }
-
- // if this is a node update (not a node add).. skip randomizer
- if (forUpdate) {
- return;
- }
-
- // Note: Placing incoming unpinned nodes at exactly the same point
- // (center of the view) causes them to explode outwards when
- // the force layout kicks in. So, we spread them out a bit
- // initially, to provide a more serene layout convergence.
- // Additionally, if the node is a host, we place it near
- // the device it is connected to.
-
- function rand() {
- return {
- x: randomService.randDim(dim[0]),
- y: randomService.randDim(dim[1])
- };
- }
-
- function near(node) {
- return {
- x: node.x + nearDist + randomService.spread(nearDist),
- y: node.y + nearDist + randomService.spread(nearDist)
- };
- }
-
- function getDevice(cp) {
- return rand();
- }
-
- xy = (node.class === 'host') ? near(getDevice(node.cp)) : rand();
-
- if (node.class === 'sub-region') {
- xy = rand();
- node.x = node.px = xy.x;
- node.y = node.py = xy.y;
- }
- angular.extend(node, xy);
- }
-
- function setLongLat(el) {
- var loc = el.get('location'),
- coord;
-
- if (loc && loc.type === 'lnglat') {
-
- if (loc.lat === 0 && loc.lng === 0) {
- return false;
- }
-
- coord = coordFromLngLat(loc);
- el.fixed = true;
- el.x = el.px = coord[0];
- el.y = el.py = coord[1];
-
- return true;
- }
- }
-
- function coordFromLngLat(loc) {
- var p = t2mcs.projection();
- return p ? p([loc.lng, loc.lat]) : [0, 0];
- }
-
angular.module('ovTopo2')
.factory('Topo2NodeModel',
- ['Topo2Model', 'FnService', 'RandomService', 'Topo2PrefsService',
+ ['Topo2Model', 'FnService', 'Topo2PrefsService',
'SvgUtilService', 'IconService', 'ThemeService',
- 'Topo2MapConfigService', 'Topo2ZoomService',
- function (Model, _fn_, _RandomService_, _ps_, _sus_, _is_, _ts_,
- _t2mcs_, zoomService) {
+ 'Topo2MapConfigService', 'Topo2ZoomService', 'Topo2NodePositionService',
+ function (Model, _fn_, _ps_, _sus_, _is_, _ts_,
+ _t2mcs_, zoomService, _t2nps_) {
- randomService = _RandomService_;
ts = _ts_;
fn = _fn_;
ps = _ps_;
sus = _sus_;
is = _is_;
t2mcs = _t2mcs_;
+ t2nps = _t2nps_;
return Model.extend({
initialize: function () {
- this.set('class', this.nodeType);
- this.set('svgClass', this.svgClassName());
this.node = this.createNode();
+ this._events = {
+ 'mouseover': 'mouseoverHandler',
+ 'mouseout': 'mouseoutHandler'
+ };
},
createNode: function () {
- this.set('class', this.nodeType);
this.set('svgClass', this.svgClassName());
- positionNode(this);
+ t2nps.positionNode(this);
return this;
},
setUpEvents: function () {
- var _this = this;
- angular.forEach(this.events, function (handler, key) {
+ var _this = this,
+ events = angular.extend({}, this._events, this.events);
+ angular.forEach(events, function (handler, key) {
_this.el.on(key, _this[handler].bind(_this));
});
},
+ mouseoverHandler: function () {
+ this.set('hovered', true);
+ },
+ mouseoutHandler: function () {
+ this.set('hovered', false);
+ },
icon: function () {
return 'unknown';
},
label: function () {
var props = this.get('props'),
id = this.get('id'),
- friendlyName = props ? props.name : id,
- labels = ['', friendlyName, id],
+ friendlyName = props && props.name ? props.name : id,
+ labels = ['', friendlyName || id, id],
nli = ps.get('dlbls'),
idx = (nli < labels.length) ? nli : 0;
@@ -197,7 +116,8 @@
return box.width + labelPad * 2;
},
addLabelElements: function (label) {
- var rect = this.el.append('rect');
+ var rect = this.el.append('rect')
+ .attr('class', 'node-container');
var glythRect = this.el.append('rect')
.attr('y', -halfDevIcon)
.attr('x', -halfDevIcon)
@@ -243,7 +163,8 @@
this.nodeType,
this.get('type'),
{
- online: this.get('online')
+ online: this.get('online'),
+ selected: this.get('selected')
}
);
},
@@ -251,6 +172,9 @@
var p = t2mcs.projection();
return p ? p.invert(coord) : [0, 0];
},
+ resetPosition: function () {
+ t2nps.setLongLat(this);
+ },
update: function () {
this.updateLabel();
},
@@ -281,8 +205,8 @@
multipler = devIconDimMax / (dim * zoomService.scale());
}
-
- this.el.selectAll('*').style('transform', 'scale(' + multipler + ')');
+ this.el.selectAll('*')
+ .style('transform', 'scale(' + multipler + ')');
},
render: function () {
var node = this.el,
@@ -293,7 +217,8 @@
// Label
var labelElements = this.addLabelElements(label);
labelWidth = label ? this.computeLabelWidth(node) : 0;
- labelElements.rect.attr(this.labelBox(devIconDim, labelWidth));
+ labelElements.rect
+ .attr(this.labelBox(devIconDim, labelWidth));
// Icon
glyph = is.addDeviceIcon(node, glyphId, devIconDim);