Topo2: Refactored Maps and Sprites to be managed by a BackgroundService
Change-Id: I75965fc76734436ce0c68e06dd75663baa924287
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
index c26c6fd..f6d62d5 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
@@ -239,6 +239,20 @@
addZoomPan(result, layout.id());
}
+ private ObjectNode initialZoomForLayout(ObjectNode zoomPrefs, String id) {
+ ObjectNode zoomForLayout = defaultZoomForLayout();
+ zoomPrefs.set(id, zoomForLayout);
+ prefService.setPreference(userName, PKEY_TOPO_ZOOM, zoomPrefs);
+ return zoomPrefs;
+ }
+
+ private ObjectNode defaultZoomForLayout() {
+ return objectNode()
+ .put(ZOOM_SCALE, DEFAULT_SCALE)
+ .put(ZOOM_PAN_X, DEFAULT_PAN)
+ .put(ZOOM_PAN_Y, DEFAULT_PAN);
+ }
+
private void addZoomPan(ObjectNode result, UiTopoLayoutId layoutId) {
// need to look up topo_zoom settings from preferences service.
@@ -254,19 +268,16 @@
ObjectNode zoomPrefs = userPrefs.get(PKEY_TOPO_ZOOM);
if (zoomPrefs == null) {
- // no zoom prefs structure yet.. so initialize..
- ObjectNode zoomForLayout = objectNode()
- .put(ZOOM_SCALE, DEFAULT_SCALE)
- .put(ZOOM_PAN_X, DEFAULT_PAN)
- .put(ZOOM_PAN_Y, DEFAULT_PAN);
-
- zoomPrefs = objectNode();
- zoomPrefs.set(layoutId.id(), zoomForLayout);
-
- prefService.setPreference(userName, PKEY_TOPO_ZOOM, zoomPrefs);
+ zoomPrefs = initialZoomForLayout(objectNode(), layoutId.id());
}
+
ObjectNode zoomData = (ObjectNode) zoomPrefs.get(layoutId.id());
+ if (zoomData == null) {
+ zoomPrefs = initialZoomForLayout(zoomPrefs, layoutId.id());
+ zoomData = (ObjectNode) zoomPrefs.get(layoutId.id());
+ }
+
result.put("bgZoomScale", zoomData.get(ZOOM_SCALE).asText());
result.put("bgZoomPanX", zoomData.get(ZOOM_PAN_X).asText());
result.put("bgZoomPanY", zoomData.get(ZOOM_PAN_Y).asText());
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2.html b/web/gui/src/main/webapp/app/view/topo2/topo2.html
index b36a036..c83c4ce 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.html
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.html
@@ -32,7 +32,7 @@
<!-- Below here is good; Above here is temporary, for debugging -->
- <svg viewBox="0 0 1000 1000"
+ <svg viewBox="0 0 1000 1000" id="topo2"
resize offset-height="56" offset-width="12"
notifier="notifyResize()">
</svg>
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2.js b/web/gui/src/main/webapp/app/view/topo2/topo2.js
index e443d39..0022964 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.js
@@ -188,36 +188,6 @@
// make sure we can respond to topology events from the server
t2es.bindHandlers();
- // Add the map SVG Group, but don't load a map yet...
- // we will wait until the server tells us whether we should
- // be loading a geomap or a sprite layer
- t2ms.init(zoomLayer, zoomer);
-
- // TODO: figure out from where to call this code...
- // we still need to do the equivalent of this when we load
- // a geo map, just not here.
- //
- // ... NOTE: we still have to position the nodes AFTER the map
- // has loaded and the projection has been established...
- // maybe another promise ending with a "positionNodes()"
- // call?
-
- // .then(
- // function (proj) {
- // var z = ps.getPrefs('topo2_zoom', { tx: 0, ty: 0, sc: 1 });
- // zoomer.panZoom([z.tx, z.ty], z.sc);
- //
- // t2mcs.projection(proj);
- // $log.debug('** Zoom restored:', z);
- // $log.debug('** We installed the projection:', proj);
- //
- // // Now the map has load and we have a projection we can
- // // get the info from the server
- // t2es.start();
- // }
- // );
-
- t2sls.init(svg, zoomLayer);
t2fs.init(svg, forceG, uplink, dim, zoomer);
t2bcs.init();
t2kcs.init(t2fs);
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Background.js b/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
new file mode 100644
index 0000000..611273b
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Background.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2017-present 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 Background Module.
+ Module that maintains the map and sprite layers
+ */
+
+(function () {
+
+ var $log;
+
+ var instance;
+
+ angular.module('ovTopo2')
+ .factory('Topo2BackgroundService', [
+ '$log', 'Topo2ViewController', 'Topo2SpriteLayerService', 'Topo2MapService',
+ 'Topo2MapConfigService', 'Topo2RegionService',
+ function (_$log_, ViewController, t2sls, t2ms, t2mcs, t2rs) {
+
+ $log = _$log_;
+
+ var BackgroundView = ViewController.extend({
+
+ id: 'topo2-background',
+ displayName: 'Background',
+
+ init: function () {
+ instance = this;
+ this.appendElement('#topo2-zoomlayer', 'g');
+ t2sls.init();
+ t2ms.init();
+ },
+ addLayout: function (data) {
+ this.background = data;
+ t2rs.bgRendered = false;
+
+ if (data.bgType === 'geo') {
+
+ // Hide Sprite Layer and show Map
+ t2sls.hide();
+ t2ms.show();
+
+ t2ms.setUpMap(data.bgId, data.bgFilePath, data.bgZoomScale)
+ .then(function (proj) {
+ // var z = ps.getPrefs('topo2_zoom', { tx: 0, ty: 0, sc: 1 });
+ // zoomer.panZoom([z.tx, z.ty], z.sc);
+
+ t2mcs.projection(proj);
+ // $log.debug('** Zoom restored:', z);
+ $log.debug('** We installed the projection:', proj);
+ t2rs.backgroundRendered();
+ });
+ }
+
+ if (data.bgType === 'grid') {
+
+ // Hide Sprite Layer and show Map
+ t2ms.hide();
+ t2sls.show();
+
+ t2sls.loadLayout(data.bgId).then(function () {
+ t2rs.backgroundRendered();
+ });
+ }
+ }
+ });
+
+
+ return instance || new BackgroundView();;
+ }
+ ]);
+})();
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js b/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js
index 84421c9..032cfb6 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Breadcrumb.js
@@ -62,8 +62,8 @@
rid: data.id
});
- layout.createForceElements();
- layout.transitionDownRegion();
+ layout().createForceElements();
+ layout().transitionDownRegion();
render();
}
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Force.js b/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
index 98c8484..1c2ea67 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
@@ -26,7 +26,7 @@
var $log,
wss;
- var t2is, t2rs, t2ls, t2vs, t2bcs, t2ss;
+ var t2is, t2rs, t2ls, t2vs, t2bcs, t2ss, t2bgs;
var svg, forceG, uplink, dim, opts, zoomer;
// D3 Selections
@@ -41,8 +41,9 @@
dim = _dim_;
opts = _opts_;
- t2ls = t2ls(svg, forceG, uplink, dim, zoomer, opts);
t2bcs.addLayout(t2ls);
+ t2bgs.init();
+ t2ls = t2ls(svg, forceG, uplink, dim, zoomer, opts);
t2rs.layout = t2ls;
t2ss.init(svg, zoomer);
}
@@ -129,8 +130,9 @@
function currentLayout(data) {
$log.debug('>> topo2CurrentLayout event:', data);
+ t2rs.clear();
t2bcs.addBreadcrumb(data.crumbs);
- t2rs.addLayout(data);
+ t2bgs.addLayout(data);
}
function currentRegion(data) {
@@ -238,8 +240,9 @@
'$log', 'WebSocketService', 'Topo2InstanceService',
'Topo2RegionService', 'Topo2LayoutService', 'Topo2ViewService',
'Topo2BreadcrumbService', 'Topo2ZoomService', 'Topo2SelectService',
+ 'Topo2BackgroundService',
function (_$log_, _wss_, _t2is_, _t2rs_, _t2ls_,
- _t2vs_, _t2bcs_, zoomService, _t2ss_) {
+ _t2vs_, _t2bcs_, zoomService, _t2ss_, _t2bgs_) {
$log = _$log_;
wss = _wss_;
@@ -249,6 +252,7 @@
t2vs = _t2vs_;
t2bcs = _t2bcs_;
t2ss = _t2ss_;
+ t2bgs = _t2bgs_;
var onZoom = function () {
var nodes = [].concat(
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
index 0d49e39..911ec18 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
@@ -17,13 +17,13 @@
(function () {
// Injected Services
- var ks, flash, wss, t2ps, t2ms, ps, t2is, t2sp, t2vs, t2rs, t2fs, t2sls;
+ var ks, flash, wss, t2ps, t2bgs, ps, t2is, t2sp, t2vs, t2rs, t2fs, t2sls;
// Commmands
var actionMap = {
L: [cycleDeviceLabels, 'Cycle device labels'],
G: [openMapSelection, 'Select background geo map'],
- B: [toggleMap, 'Toggle background geo map'],
+ B: [toggleBackground, 'Toggle background'],
I: [toggleInstancePanel, 'Toggle ONOS Instance Panel'],
O: [toggleSummary, 'Toggle the Summary Panel'],
R: [resetZoom, 'Reset pan / zoom'],
@@ -31,7 +31,6 @@
E: [equalizeMasters, 'Equalize mastership roles'],
X: [resetAllNodeLocations, 'Reset Node Location'],
U: [unpinNode, 'Unpin node (mouse over)'],
- S: [toggleSpriteLayer, 'Toggle sprite layer'],
esc: handleEscape
};
@@ -103,8 +102,8 @@
t2ms.openMapSelection();
}
- function toggleMap(x) {
- t2ms.toggle(x);
+ function toggleBackground(x) {
+ t2bgs.toggle(x);
}
function toggleInstancePanel(x) {
@@ -120,10 +119,6 @@
flash.flash('Pan and zoom reset');
}
- function toggleSpriteLayer() {
- t2sls.toggle();
- }
-
function togglePorts(x) {
updatePrefsState('porthl', t2vs.togglePortHighlights(x));
t2fs.updateLinks();
@@ -147,17 +142,17 @@
angular.module('ovTopo2')
.factory('Topo2KeyCommandService', [
'KeyService', 'FlashService', 'WebSocketService', 'Topo2PrefsService',
- 'Topo2MapService', 'PrefsService', 'Topo2InstanceService',
+ 'Topo2BackgroundService', 'PrefsService', 'Topo2InstanceService',
'Topo2SummaryPanelService', 'Topo2ViewService', 'Topo2RegionService',
'Topo2SpriteLayerService',
- function (_ks_, _flash_, _wss_, _t2ps_, _t2ms_, _ps_, _t2is_, _t2sp_,
+ function (_ks_, _flash_, _wss_, _t2ps_, _t2bgs_, _ps_, _t2is_, _t2sp_,
_t2vs_, _t2rs_, _t2sls_) {
ks = _ks_;
flash = _flash_;
wss = _wss_;
t2ps = _t2ps_;
- t2ms = _t2ms_;
+ t2bgs = _t2bgs_;
t2is = _t2is_;
ps = _ps_;
t2sp = _t2sp_;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
index 9350020..75105ba 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
@@ -98,7 +98,6 @@
var Layout = ViewController.extend({
initialize: function (svg, forceG, uplink, dim, zoomer, opts) {
-
$log.debug('initialize Layout');
instance = this;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
index 69716d8..0f559fa 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
@@ -23,7 +23,7 @@
'use strict';
// Injected Services
- var $log, $loc, ps, ms, flash, sus, countryFilters;
+ var $log, $loc, ps, ms, flash, sus, t2zs, countryFilters;
// Injected Classes
var MapSelectionDialog;
@@ -31,43 +31,26 @@
// internal state
var instance, mapG, zoomLayer, zoomer;
- function init(_zoomLayer_, _zoomer_) {
- zoomLayer = _zoomLayer_;
- zoomer = _zoomer_;
- // This function no longer returns a promise.
- // TODO: call setUpMap() when we know which map we want (not from here)
- // return setUpMap.bind(this)();
+ function init() {
+ this.appendElement('#topo2-background', 'g');
+ zoomLayer = d3.select('#topo2-zoomlayer');
+ zoomer = t2zs.getZoomer();
}
// TODO: to be re-worked: map-id, filePath, scale/pan to be passed as params
- function setUpMap() {
- var prefs = currentMap(),
- mapId = prefs.mapid,
- mapFilePath = prefs.mapfilepath,
- mapScale = prefs.mapscale || 1,
- loadMap = ms.loadMapInto,
+ function setUpMap(mapId, mapFilePath, mapScale) {
+
+ var loadMap = ms.loadMapInto,
promise, cfilter;
- mapG = d3.select('#topo2-map');
-
- if (mapG.empty()) {
- mapG = zoomLayer.append('g').attr('id', 'topo2-map');
- } else {
- mapG.each(function () {
- d3.selectAll(this.childNodes).remove();
- });
- }
-
- if (!ps.getPrefs('topo2_prefs')[this.prefs.visible]) {
- this.hide();
- }
+ this.node().selectAll("*").remove();
if (mapFilePath === '*countries') {
cfilter = countryFilters[mapId] || countryFilters.uk;
loadMap = ms.loadMapRegionInto;
}
- promise = loadMap(mapG, mapFilePath, mapId, {
+ promise = loadMap(this.node(), mapFilePath, mapId, {
countryFilters: cfilter,
adjustScale: mapScale,
shading: ''
@@ -118,11 +101,11 @@
.factory('Topo2MapService', [
'$log', '$location', 'Topo2ViewController', 'PrefsService',
'MapService', 'FlashService', 'SvgUtilService', 'Topo2CountryFilters',
- 'Topo2MapDialog',
+ 'Topo2MapDialog', 'Topo2ZoomService',
function (_$log_, _$loc_, ViewController, _ps_,
_ms_, _flash_, _sus_, _t2cf_,
- _t2md_) {
+ _t2md_, _t2zs_) {
$log = _$log_;
$loc = _$loc_;
@@ -132,6 +115,7 @@
sus = _sus_;
countryFilters = _t2cf_;
MapSelectionDialog = _t2md_;
+ t2zs = _t2zs_;
var MapLayer = ViewController.extend({
@@ -140,6 +124,7 @@
init: init,
setMap: setMap,
+ setUpMap: setUpMap,
openMapSelection: openMapSelection,
resetZoom: resetZoom
});
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js
index aeac6d4..e29c45b 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodePosition.js
@@ -134,6 +134,7 @@
// 1000 is a hardcoded HTML value of the SVG element (topo2.html)
var x = scale * loc.gridX,
y = (scale * loc.gridY) + yOffset;
+
return [x, y];
}
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
index 0202ca9..54c88c7 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
@@ -45,39 +45,24 @@
initialize: function () {
instance = this;
this.model = null;
+ this.bgRendered = false;
},
- addLayout: function (data) {
+ backgroundRendered: function () {
+ this.bgRendered = true;
- var _this = this;
-
- if (data.bgType === 'geo') {
- t2ms.setMap({
- mapid: data.bgId,
- mapfilepath: data.bgFilePath
- }).then(function () {
- _.each(_this.regionNodes(), function (node) {
- node.resetPosition();
- });
- });
-
- if (t2ms.enabled()) {
- t2ms.show();
- }
- } else {
- t2ms.hide();
- }
-
- if (data.bgType === 'grid') {
- t2sls.loadLayout(data.bgId);
-
- if (t2sls.enabled()) {
- t2sls.show();
- }
- } else {
- t2sls.hide();
+ if (this.regionData) {
+ this.startRegion();
}
},
addRegion: function (data) {
+ this.clear();
+ this.regionData = data;
+
+ if (this.bgRendered) {
+ this.startRegion();
+ }
+ },
+ startRegion: function () {
var RegionModel = Model.extend({
findNodeById: this.findNodeById,
@@ -85,15 +70,15 @@
});
this.model = new RegionModel({
- id: data.id,
- layerOrder: data.layerOrder
+ id: this.regionData.id,
+ layerOrder: this.regionData.layerOrder
});
this.model.set({
- subregions: t2sr.createSubRegionCollection(data.subregions, this),
- devices: t2ds.createDeviceCollection(data.devices, this),
- hosts: t2hs.createHostCollection(data.hosts, this),
- links: t2ls.createLinkCollection(data.links, this)
+ subregions: t2sr.createSubRegionCollection(this.regionData.subregions, this),
+ devices: t2ds.createDeviceCollection(this.regionData.devices, this),
+ hosts: t2hs.createHostCollection(this.regionData.hosts, this),
+ links: t2ls.createLinkCollection(this.regionData.links, this)
});
angular.forEach(this.model.get('links').models, function (link) {
@@ -105,6 +90,23 @@
t2bcs.hide();
}
+ // this.layout.update();
+ },
+ clear: function () {
+
+ this.regionData = null;
+
+ if (!this.model)
+ return;
+
+ this.model.set({
+ id: null,
+ layerOrder: null,
+ subregions: t2sr.createSubRegionCollection([], this),
+ devices: t2ds.createDeviceCollection([], this),
+ hosts: t2hs.createHostCollection([], this),
+ links: t2ls.createLinkCollection([], this)
+ });
},
isRootRegion: function () {
return this.model.get('id') === ROOT;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js b/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
index 17c4262..6de99fe 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SpriteLayer.js
@@ -40,10 +40,10 @@
id: 'topo2-sprites',
displayName: 'Sprite Layer',
- init: function(svg, zoomLayer) {
- this.svg = svg;
+ init: function() {
+ this.svg = d3.select('#topo2');
this.createSpriteDefs();
- this.container = zoomLayer.append('g').attr('id', this.id);
+ this.container = this.appendElement('#topo2-background', 'g');
},
loadLayout: function (id) {
this.container.selectAll("*").remove();
@@ -57,6 +57,11 @@
if (fs.debugOn('sprite_grid')) {
this.renderGrid();
}
+
+ // Returns a promise for consistency with Topo2MapService
+ return new Promise(function(resolve) {
+ resolve();
+ });
},
createSpriteDefs: function () {
this.defs = this.svg.append('defs')
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js b/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js
index ad8dfa9..6c19fe9 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2ViewController.js
@@ -39,6 +39,13 @@
visible: this.name + '_visible'
}
},
+ appendElement: function (parent, node) {
+ var el = d3.select('#' + this.id);
+ if (el.empty()) {
+ return d3.select(parent).append(node).attr('id', this.id);
+ }
+ return el;
+ },
node: function() {
return d3.select('#' + this.id);
},
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index f053f02..3930779 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -134,6 +134,7 @@
<!-- Under development for Region support. -->
<!--<script src="app/view/topo2/topo2.js"></script>
<script src="app/view/topo2/topo2Breadcrumb.js"></script>
+ <script src="app/view/topo2/topo2Background.js"></script>
<script src="app/view/topo2/topo2Collection.js"></script>
<script src="app/view/topo2/topo2D3.js"></script>
<script src="app/view/topo2/topo2Dialog.js"></script>