Added Map Dialog
Added Map Background
Prevent click on node drag event
Change-Id: Ibb13085e3aa51eae49a2017251486f00d52f6265
diff --git a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
index 0f375e2..60a8be1 100644
--- a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
+++ b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
@@ -104,6 +104,8 @@
}
})
.on('dragend', function(d) {
+ d3.event.sourceEvent.preventDefault();
+
if (d.dragStarted) {
d.dragStarted = false;
if (!dragged(d)) {
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 fa3b36e..ccc50e0 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.js
@@ -25,7 +25,7 @@
// references to injected services
var $scope, $log, fs, mast, ks, zs,
- gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs;
+ gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms;
// DOM elements
var ovtopo2, svg, defs, zoomLayer, forceG;
@@ -87,13 +87,13 @@
'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
'WebSocketService', 'PrefsService', 'ThemeService',
'Topo2EventService', 'Topo2ForceService', 'Topo2InstanceService',
- 'Topo2BreadcrumbService', 'Topo2KeyCommandService',
+ 'Topo2BreadcrumbService', 'Topo2KeyCommandService', 'Topo2MapService',
function (_$scope_, _$log_, _$loc_,
_fs_, _mast_, _ks_, _zs_,
_gs_, _ms_, _sus_, _flash_,
_wss_, _ps_, _th_,
- _t2es_, _t2fs_, _t2is_, _t2bcs_, _t2kcs_) {
+ _t2es_, _t2fs_, _t2is_, _t2bcs_, _t2kcs_, _t2ms_) {
var params = _$loc_.search(),
dim,
@@ -126,8 +126,7 @@
t2is = _t2is_;
t2bcs = _t2bcs_;
t2kcs = _t2kcs_;
-
- t2kcs.init(t2fs);
+ t2ms = _t2ms_;
// capture selected intent parameters (if they are set in the
// query string) so that the traffic overlay can highlight
@@ -172,10 +171,22 @@
// make sure we can respond to topology events from the server
t2es.bindHandlers();
+ // Add the map SVG Group
+ t2ms.init(zoomLayer).then(
+ function (proj) {
+ var z = ps.getPrefs('topo_zoom', { tx: 0, ty: 0, sc: 1 });
+ zoomer.panZoom([z.tx, z.ty], z.sc);
+ $log.debug('** Zoom restored:', z);
+ $log.debug('** We installed the projection:', proj);
+ }
+ );
+
// initialize the force layout, ready to render the topology
forceG = zoomLayer.append('g').attr('id', 'topo-force');
t2fs.init(svg, forceG, uplink, dim);
t2bcs.init();
+ t2kcs.init(t2fs);
+
// =-=-=-=-=-=-=-=-
// TODO: in future, we will load background map data
@@ -188,34 +199,9 @@
// === ORIGINAL CODE ===
- // setUpKeys();
// setUpToolbar();
- // setUpDefs();
- // setUpZoom();
// setUpNoDevs();
- /*
- setUpMap().then(
- function (proj) {
- var z = ps.getPrefs('topo_zoom', { tx:0, ty:0, sc:1 });
- zoomer.panZoom([z.tx, z.ty], z.sc);
- $log.debug('** Zoom restored:', z);
- projection = proj;
- $log.debug('** We installed the projection:', proj);
- flash.enable(false);
- toggleMap(prefsState.bg);
- flash.enable(true);
- mapShader(true);
-
- // now we have the map projection, we are ready for
- // the server to send us device/host data...
- tes.start();
- // need to do the following so we immediately get
- // the summary panel data back from the server
- restoreSummaryFromPrefs();
- }
- );
- */
// tes.bindHandlers();
// setUpSprites();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Dialog.js b/web/gui/src/main/webapp/app/view/topo2/topo2Dialog.js
new file mode 100644
index 0000000..13da1a8
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Dialog.js
@@ -0,0 +1,46 @@
+/*
+* Copyright 2016-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 Dialog Module.
+ Creates a dialog box for the topology view.
+ */
+
+(function () {
+ 'use strict';
+
+ // constants
+ var idDialog = 'topo-p-dialog',
+ opts = {
+ cssCls: 'topo-p'
+ };
+
+ // ==========================
+
+ angular.module('ovTopo2')
+ .factory('Topo2DialogService',
+ ['DialogService',
+
+ function (ds) {
+ return {
+ openDialog: function () {
+ return ds.openDialog(idDialog, opts);
+ },
+ closeDialog: ds.closeDialog,
+ createDiv: ds.createDiv
+ };
+ }]);
+})();
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 f3b444d..ea6436d 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2KeyCommands.js
@@ -17,12 +17,14 @@
(function () {
// Injected Services
- var ks, t2ps;
+ var ks, t2ps, t2ms;
var topo2ForceService;
// Commmands
var actionMap = {
- L: [cycleDeviceLabels, 'Cycle device labels']
+ L: [cycleDeviceLabels, 'Cycle device labels'],
+ G: [openMapSelection, 'Select background geo map'],
+ B: [toggleMap, 'Toggle background geo map'],
};
function init(t2fs) {
@@ -49,13 +51,22 @@
topo2ForceService.updateNodes();
}
+ function openMapSelection() {
+ t2ms.openMapSelection();
+ }
+
+ function toggleMap(x) {
+ t2ms.toggle(x);
+ }
+
angular.module('ovTopo2')
.factory('Topo2KeyCommandService',
- ['KeyService', 'Topo2PrefsService',
+ ['KeyService', 'Topo2PrefsService', 'Topo2MapService',
- function (_ks_, _t2ps_) {
+ function (_ks_, _t2ps_, _t2ms_) {
t2ps = _t2ps_;
+ t2ms = _t2ms_;
ks = _ks_;
return {
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Map.js b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
new file mode 100644
index 0000000..4576528
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Map.js
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2016-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 Map Module.
+ Defines behavior for loading geographical maps into the map layer.
+ */
+
+(function () {
+ 'use strict';
+
+ var $log, $loc, wss, ps, ms, t2ds, sus;
+
+ // internal state
+ var mapG, order, maps, map, mapItems, tintCheck, messageHandlers;
+
+ // constants
+ var mapRequest = 'mapSelectorRequest';
+
+ var countryFilters = {
+ s_america: function (c) {
+ return c.properties.continent === 'South America';
+ },
+
+ ns_america: function (c) {
+ return c.properties.custom === 'US-cont' ||
+ c.properties.subregion === 'Central America' ||
+ c.properties.continent === 'South America';
+ },
+
+ japan: function (c) {
+ return c.properties.geounit === 'Japan';
+ },
+
+ europe: function (c) {
+ return c.properties.continent === 'Europe';
+ },
+
+ italy: function (c) {
+ return c.properties.geounit === 'Italy';
+ },
+
+ uk: function (c) {
+ // technically, Ireland is not part of the United Kingdom,
+ // but the map looks weird without it showing.
+ return c.properties.adm0_a3 === 'GBR' ||
+ c.properties.adm0_a3 === 'IRL';
+ },
+
+ s_korea: function (c) {
+ return c.properties.adm0_a3 === 'KOR';
+ },
+
+ australia: function (c) {
+ return c.properties.adm0_a3 === 'AUS';
+ }
+ };
+
+ function init(zoomLayer) {
+
+ start();
+ return setUpMap(zoomLayer);
+ }
+
+ function setUpMap(zoomLayer) {
+ var prefs = currentMap(),
+ mapId = prefs.mapid,
+ mapFilePath = prefs.mapfilepath,
+ mapScale = prefs.mapscale,
+ tint = prefs.tint,
+ promise, cfilter;
+
+ mapG = d3.select('#topo-map');
+
+ if (mapG.empty()) {
+ mapG = zoomLayer.append('g').attr('id', 'topo-map');
+ } else {
+ mapG.each(function (d, i) {
+ d3.selectAll(this.childNodes).remove();
+ });
+ }
+
+ cfilter = countryFilters[mapId] || countryFilters.uk;
+
+ if (mapFilePath === '*countries') {
+
+ cfilter = countryFilters[mapId] || countryFilters.uk;
+
+ promise = ms.loadMapRegionInto(mapG, {
+ countryFilter: cfilter,
+ adjustScale: mapScale,
+ shading: ''
+ });
+ } else {
+
+ promise = ms.loadMapInto(mapG, mapFilePath, mapId, {
+ adjustScale: mapScale,
+ shading: ''
+ });
+ }
+
+ return promise;
+ }
+
+ function start() {
+ wss.bindHandlers(messageHandlers);
+ }
+
+ function stop() {
+ wss.unbindHandlers(messageHandlers);
+ }
+
+ function currentMap() {
+ return ps.getPrefs(
+ 'topo_mapid',
+ {
+ mapid: 'usa',
+ mapscale: 1,
+ mapfilepath: '*continental_us',
+ tint: 'off'
+ },
+ $loc.search()
+ );
+ }
+
+ function openMapSelection() {
+ wss.sendEvent(mapRequest);
+ }
+
+ function opacifyMap(b) {
+ mapG.transition()
+ .duration(1000)
+ .attr('opacity', b ? 1 : 0);
+ }
+
+ function setMap(map) {
+ ps.setPrefs('topo_mapid', map);
+ setUpMap();
+ opacifyMap(true);
+ }
+
+ function dOk() {
+ var p = {
+ mapid: map.id,
+ mapscale: map.scale,
+ mapfilepath: map.filePath,
+ tint: 'off'
+ // tint: tintCheck.property('checked') ? 'on' : 'off'
+ };
+ setMap(p);
+ $log.debug('Dialog OK button clicked');
+ }
+
+ function dClose() {
+ $log.debug('Dialog Close button clicked (or Esc pressed)');
+ }
+
+ function selectMap() {
+ map = maps[this.options[this.selectedIndex].value];
+ $log.info('Selected map', map);
+ }
+
+ function createListContent() {
+ var content = t2ds.createDiv('map-list'),
+ form = content.append('form'),
+ current = currentMap();
+ map = maps[current.mapid];
+ mapItems = form.append('select').on('change', selectMap);
+ order.forEach(function (id) {
+ var m = maps[id];
+ mapItems.append('option')
+ .attr('value', m.id)
+ .attr('selected', m.id === current.mapid ? true : null)
+ .text(m.description);
+ });
+
+ return content;
+ }
+
+ function handleMapResponse(data) {
+ $log.info('Got response', data);
+ order = data.order;
+ maps = data.maps;
+ t2ds.openDialog()
+ .setTitle('Select Map')
+ .addContent(createListContent())
+ .addOk(dOk, 'OK')
+ .addCancel(dClose, 'Close')
+ .bindKeys();
+ }
+
+ // TODO: -- START -- Move to dedicated module
+ var prefsState = {};
+
+ function updatePrefsState(what, b) {
+ prefsState[what] = b ? 1 : 0;
+ ps.setPrefs('topo_prefs', prefsState);
+ }
+
+ function _togSvgLayer(x, G, tag, what) {
+ var on = (x === 'keyev') ? !sus.visible(G) : !!x,
+ verb = on ? 'Show' : 'Hide';
+ sus.visible(G, on);
+ updatePrefsState(tag, on);
+ // flash.flash(verb + ' ' + what);
+ }
+ // TODO: -- END -- Move to dedicated module
+
+ function toggle(x) {
+ _togSvgLayer(x, mapG, 'bg', 'background map');
+ }
+
+ angular.module('ovTopo2')
+ .factory('Topo2MapService',
+ ['$log', '$location', 'WebSocketService', 'PrefsService', 'MapService',
+ 'SvgUtilService', 'Topo2DialogService',
+ function (_$log_, _$loc_, _wss_, _ps_, _ms_, _sus_, _t2ds_) {
+
+ $log = _$log_;
+ $loc = _$loc_;
+ wss = _wss_;
+ ps = _ps_;
+ ms = _ms_;
+ sus = _sus_;
+ t2ds = _t2ds_;
+
+ messageHandlers = {
+ mapSelectorResponse: handleMapResponse
+ };
+
+ return {
+ init: init,
+ openMapSelection: openMapSelection,
+ toggle: toggle,
+ stop: stop
+ };
+ }
+ ]);
+
+})();
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
index dad55f5..2dd7997 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
@@ -75,6 +75,9 @@
nodeType: 'sub-region',
mapDeviceTypeToGlyph: mapDeviceTypeToGlyph,
onClick: function () {
+
+ if (d3.event.defaultPrevented) return;
+
wss.sendEvent('topo2navRegion', {
dir: 'down',
rid: this.get('id')
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index 2b6fc57..beef418 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -130,6 +130,7 @@
<script src="app/view/topo2/topo2Breadcrumb.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>
<script src="app/view/topo2/topo2Device.js"></script>
<script src="app/view/topo2/topo2Event.js"></script>
<script src="app/view/topo2/topo2Force.js"></script>
@@ -138,6 +139,7 @@
<script src="app/view/topo2/topo2KeyCommands.js"></script>
<script src="app/view/topo2/topo2Layout.js"></script>
<script src="app/view/topo2/topo2Link.js"></script>
+ <script src="app/view/topo2/topo2Map.js"></script>
<script src="app/view/topo2/topo2Model.js"></script>
<script src="app/view/topo2/topo2NodeModel.js"></script>
<script src="app/view/topo2/topo2Prefs.js"></script>