Steven Burrows

Added Map Dialog

Added Map Background
Prevent click on node drag event

Change-Id: Ibb13085e3aa51eae49a2017251486f00d52f6265
...@@ -104,6 +104,8 @@ ...@@ -104,6 +104,8 @@
104 } 104 }
105 }) 105 })
106 .on('dragend', function(d) { 106 .on('dragend', function(d) {
107 + d3.event.sourceEvent.preventDefault();
108 +
107 if (d.dragStarted) { 109 if (d.dragStarted) {
108 d.dragStarted = false; 110 d.dragStarted = false;
109 if (!dragged(d)) { 111 if (!dragged(d)) {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
25 25
26 // references to injected services 26 // references to injected services
27 var $scope, $log, fs, mast, ks, zs, 27 var $scope, $log, fs, mast, ks, zs,
28 - gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs; 28 + gs, sus, ps, t2es, t2fs, t2is, t2bcs, t2kcs, t2ms;
29 29
30 // DOM elements 30 // DOM elements
31 var ovtopo2, svg, defs, zoomLayer, forceG; 31 var ovtopo2, svg, defs, zoomLayer, forceG;
...@@ -87,13 +87,13 @@ ...@@ -87,13 +87,13 @@
87 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService', 87 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
88 'WebSocketService', 'PrefsService', 'ThemeService', 88 'WebSocketService', 'PrefsService', 'ThemeService',
89 'Topo2EventService', 'Topo2ForceService', 'Topo2InstanceService', 89 'Topo2EventService', 'Topo2ForceService', 'Topo2InstanceService',
90 - 'Topo2BreadcrumbService', 'Topo2KeyCommandService', 90 + 'Topo2BreadcrumbService', 'Topo2KeyCommandService', 'Topo2MapService',
91 91
92 function (_$scope_, _$log_, _$loc_, 92 function (_$scope_, _$log_, _$loc_,
93 _fs_, _mast_, _ks_, _zs_, 93 _fs_, _mast_, _ks_, _zs_,
94 _gs_, _ms_, _sus_, _flash_, 94 _gs_, _ms_, _sus_, _flash_,
95 _wss_, _ps_, _th_, 95 _wss_, _ps_, _th_,
96 - _t2es_, _t2fs_, _t2is_, _t2bcs_, _t2kcs_) { 96 + _t2es_, _t2fs_, _t2is_, _t2bcs_, _t2kcs_, _t2ms_) {
97 97
98 var params = _$loc_.search(), 98 var params = _$loc_.search(),
99 dim, 99 dim,
...@@ -126,8 +126,7 @@ ...@@ -126,8 +126,7 @@
126 t2is = _t2is_; 126 t2is = _t2is_;
127 t2bcs = _t2bcs_; 127 t2bcs = _t2bcs_;
128 t2kcs = _t2kcs_; 128 t2kcs = _t2kcs_;
129 - 129 + t2ms = _t2ms_;
130 - t2kcs.init(t2fs);
131 130
132 // capture selected intent parameters (if they are set in the 131 // capture selected intent parameters (if they are set in the
133 // query string) so that the traffic overlay can highlight 132 // query string) so that the traffic overlay can highlight
...@@ -172,10 +171,22 @@ ...@@ -172,10 +171,22 @@
172 // make sure we can respond to topology events from the server 171 // make sure we can respond to topology events from the server
173 t2es.bindHandlers(); 172 t2es.bindHandlers();
174 173
174 + // Add the map SVG Group
175 + t2ms.init(zoomLayer).then(
176 + function (proj) {
177 + var z = ps.getPrefs('topo_zoom', { tx: 0, ty: 0, sc: 1 });
178 + zoomer.panZoom([z.tx, z.ty], z.sc);
179 + $log.debug('** Zoom restored:', z);
180 + $log.debug('** We installed the projection:', proj);
181 + }
182 + );
183 +
175 // initialize the force layout, ready to render the topology 184 // initialize the force layout, ready to render the topology
176 forceG = zoomLayer.append('g').attr('id', 'topo-force'); 185 forceG = zoomLayer.append('g').attr('id', 'topo-force');
177 t2fs.init(svg, forceG, uplink, dim); 186 t2fs.init(svg, forceG, uplink, dim);
178 t2bcs.init(); 187 t2bcs.init();
188 + t2kcs.init(t2fs);
189 +
179 190
180 // =-=-=-=-=-=-=-=- 191 // =-=-=-=-=-=-=-=-
181 // TODO: in future, we will load background map data 192 // TODO: in future, we will load background map data
...@@ -188,34 +199,9 @@ ...@@ -188,34 +199,9 @@
188 199
189 // === ORIGINAL CODE === 200 // === ORIGINAL CODE ===
190 201
191 - // setUpKeys();
192 // setUpToolbar(); 202 // setUpToolbar();
193 - // setUpDefs();
194 - // setUpZoom();
195 // setUpNoDevs(); 203 // setUpNoDevs();
196 - /*
197 - setUpMap().then(
198 - function (proj) {
199 - var z = ps.getPrefs('topo_zoom', { tx:0, ty:0, sc:1 });
200 - zoomer.panZoom([z.tx, z.ty], z.sc);
201 - $log.debug('** Zoom restored:', z);
202 204
203 - projection = proj;
204 - $log.debug('** We installed the projection:', proj);
205 - flash.enable(false);
206 - toggleMap(prefsState.bg);
207 - flash.enable(true);
208 - mapShader(true);
209 -
210 - // now we have the map projection, we are ready for
211 - // the server to send us device/host data...
212 - tes.start();
213 - // need to do the following so we immediately get
214 - // the summary panel data back from the server
215 - restoreSummaryFromPrefs();
216 - }
217 - );
218 - */
219 // tes.bindHandlers(); 205 // tes.bindHandlers();
220 // setUpSprites(); 206 // setUpSprites();
221 207
......
1 +/*
2 +* Copyright 2016-present Open Networking Laboratory
3 +*
4 +* Licensed under the Apache License, Version 2.0 (the "License");
5 +* you may not use this file except in compliance with the License.
6 +* You may obtain a copy of the License at
7 +*
8 +* http://www.apache.org/licenses/LICENSE-2.0
9 +*
10 +* Unless required by applicable law or agreed to in writing, software
11 +* distributed under the License is distributed on an "AS IS" BASIS,
12 +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 +* See the License for the specific language governing permissions and
14 +* limitations under the License.
15 +*/
16 +
17 +/*
18 + ONOS GUI -- Topology Dialog Module.
19 + Creates a dialog box for the topology view.
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + // constants
26 + var idDialog = 'topo-p-dialog',
27 + opts = {
28 + cssCls: 'topo-p'
29 + };
30 +
31 + // ==========================
32 +
33 + angular.module('ovTopo2')
34 + .factory('Topo2DialogService',
35 + ['DialogService',
36 +
37 + function (ds) {
38 + return {
39 + openDialog: function () {
40 + return ds.openDialog(idDialog, opts);
41 + },
42 + closeDialog: ds.closeDialog,
43 + createDiv: ds.createDiv
44 + };
45 + }]);
46 +})();
...@@ -17,12 +17,14 @@ ...@@ -17,12 +17,14 @@
17 (function () { 17 (function () {
18 18
19 // Injected Services 19 // Injected Services
20 - var ks, t2ps; 20 + var ks, t2ps, t2ms;
21 var topo2ForceService; 21 var topo2ForceService;
22 22
23 // Commmands 23 // Commmands
24 var actionMap = { 24 var actionMap = {
25 - L: [cycleDeviceLabels, 'Cycle device labels'] 25 + L: [cycleDeviceLabels, 'Cycle device labels'],
26 + G: [openMapSelection, 'Select background geo map'],
27 + B: [toggleMap, 'Toggle background geo map'],
26 }; 28 };
27 29
28 function init(t2fs) { 30 function init(t2fs) {
...@@ -49,13 +51,22 @@ ...@@ -49,13 +51,22 @@
49 topo2ForceService.updateNodes(); 51 topo2ForceService.updateNodes();
50 } 52 }
51 53
54 + function openMapSelection() {
55 + t2ms.openMapSelection();
56 + }
57 +
58 + function toggleMap(x) {
59 + t2ms.toggle(x);
60 + }
61 +
52 angular.module('ovTopo2') 62 angular.module('ovTopo2')
53 .factory('Topo2KeyCommandService', 63 .factory('Topo2KeyCommandService',
54 - ['KeyService', 'Topo2PrefsService', 64 + ['KeyService', 'Topo2PrefsService', 'Topo2MapService',
55 65
56 - function (_ks_, _t2ps_) { 66 + function (_ks_, _t2ps_, _t2ms_) {
57 67
58 t2ps = _t2ps_; 68 t2ps = _t2ps_;
69 + t2ms = _t2ms_;
59 ks = _ks_; 70 ks = _ks_;
60 71
61 return { 72 return {
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Topology Map Module.
19 + Defines behavior for loading geographical maps into the map layer.
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + var $log, $loc, wss, ps, ms, t2ds, sus;
26 +
27 + // internal state
28 + var mapG, order, maps, map, mapItems, tintCheck, messageHandlers;
29 +
30 + // constants
31 + var mapRequest = 'mapSelectorRequest';
32 +
33 + var countryFilters = {
34 + s_america: function (c) {
35 + return c.properties.continent === 'South America';
36 + },
37 +
38 + ns_america: function (c) {
39 + return c.properties.custom === 'US-cont' ||
40 + c.properties.subregion === 'Central America' ||
41 + c.properties.continent === 'South America';
42 + },
43 +
44 + japan: function (c) {
45 + return c.properties.geounit === 'Japan';
46 + },
47 +
48 + europe: function (c) {
49 + return c.properties.continent === 'Europe';
50 + },
51 +
52 + italy: function (c) {
53 + return c.properties.geounit === 'Italy';
54 + },
55 +
56 + uk: function (c) {
57 + // technically, Ireland is not part of the United Kingdom,
58 + // but the map looks weird without it showing.
59 + return c.properties.adm0_a3 === 'GBR' ||
60 + c.properties.adm0_a3 === 'IRL';
61 + },
62 +
63 + s_korea: function (c) {
64 + return c.properties.adm0_a3 === 'KOR';
65 + },
66 +
67 + australia: function (c) {
68 + return c.properties.adm0_a3 === 'AUS';
69 + }
70 + };
71 +
72 + function init(zoomLayer) {
73 +
74 + start();
75 + return setUpMap(zoomLayer);
76 + }
77 +
78 + function setUpMap(zoomLayer) {
79 + var prefs = currentMap(),
80 + mapId = prefs.mapid,
81 + mapFilePath = prefs.mapfilepath,
82 + mapScale = prefs.mapscale,
83 + tint = prefs.tint,
84 + promise, cfilter;
85 +
86 + mapG = d3.select('#topo-map');
87 +
88 + if (mapG.empty()) {
89 + mapG = zoomLayer.append('g').attr('id', 'topo-map');
90 + } else {
91 + mapG.each(function (d, i) {
92 + d3.selectAll(this.childNodes).remove();
93 + });
94 + }
95 +
96 + cfilter = countryFilters[mapId] || countryFilters.uk;
97 +
98 + if (mapFilePath === '*countries') {
99 +
100 + cfilter = countryFilters[mapId] || countryFilters.uk;
101 +
102 + promise = ms.loadMapRegionInto(mapG, {
103 + countryFilter: cfilter,
104 + adjustScale: mapScale,
105 + shading: ''
106 + });
107 + } else {
108 +
109 + promise = ms.loadMapInto(mapG, mapFilePath, mapId, {
110 + adjustScale: mapScale,
111 + shading: ''
112 + });
113 + }
114 +
115 + return promise;
116 + }
117 +
118 + function start() {
119 + wss.bindHandlers(messageHandlers);
120 + }
121 +
122 + function stop() {
123 + wss.unbindHandlers(messageHandlers);
124 + }
125 +
126 + function currentMap() {
127 + return ps.getPrefs(
128 + 'topo_mapid',
129 + {
130 + mapid: 'usa',
131 + mapscale: 1,
132 + mapfilepath: '*continental_us',
133 + tint: 'off'
134 + },
135 + $loc.search()
136 + );
137 + }
138 +
139 + function openMapSelection() {
140 + wss.sendEvent(mapRequest);
141 + }
142 +
143 + function opacifyMap(b) {
144 + mapG.transition()
145 + .duration(1000)
146 + .attr('opacity', b ? 1 : 0);
147 + }
148 +
149 + function setMap(map) {
150 + ps.setPrefs('topo_mapid', map);
151 + setUpMap();
152 + opacifyMap(true);
153 + }
154 +
155 + function dOk() {
156 + var p = {
157 + mapid: map.id,
158 + mapscale: map.scale,
159 + mapfilepath: map.filePath,
160 + tint: 'off'
161 + // tint: tintCheck.property('checked') ? 'on' : 'off'
162 + };
163 + setMap(p);
164 + $log.debug('Dialog OK button clicked');
165 + }
166 +
167 + function dClose() {
168 + $log.debug('Dialog Close button clicked (or Esc pressed)');
169 + }
170 +
171 + function selectMap() {
172 + map = maps[this.options[this.selectedIndex].value];
173 + $log.info('Selected map', map);
174 + }
175 +
176 + function createListContent() {
177 + var content = t2ds.createDiv('map-list'),
178 + form = content.append('form'),
179 + current = currentMap();
180 + map = maps[current.mapid];
181 + mapItems = form.append('select').on('change', selectMap);
182 + order.forEach(function (id) {
183 + var m = maps[id];
184 + mapItems.append('option')
185 + .attr('value', m.id)
186 + .attr('selected', m.id === current.mapid ? true : null)
187 + .text(m.description);
188 + });
189 +
190 + return content;
191 + }
192 +
193 + function handleMapResponse(data) {
194 + $log.info('Got response', data);
195 + order = data.order;
196 + maps = data.maps;
197 + t2ds.openDialog()
198 + .setTitle('Select Map')
199 + .addContent(createListContent())
200 + .addOk(dOk, 'OK')
201 + .addCancel(dClose, 'Close')
202 + .bindKeys();
203 + }
204 +
205 + // TODO: -- START -- Move to dedicated module
206 + var prefsState = {};
207 +
208 + function updatePrefsState(what, b) {
209 + prefsState[what] = b ? 1 : 0;
210 + ps.setPrefs('topo_prefs', prefsState);
211 + }
212 +
213 + function _togSvgLayer(x, G, tag, what) {
214 + var on = (x === 'keyev') ? !sus.visible(G) : !!x,
215 + verb = on ? 'Show' : 'Hide';
216 + sus.visible(G, on);
217 + updatePrefsState(tag, on);
218 + // flash.flash(verb + ' ' + what);
219 + }
220 + // TODO: -- END -- Move to dedicated module
221 +
222 + function toggle(x) {
223 + _togSvgLayer(x, mapG, 'bg', 'background map');
224 + }
225 +
226 + angular.module('ovTopo2')
227 + .factory('Topo2MapService',
228 + ['$log', '$location', 'WebSocketService', 'PrefsService', 'MapService',
229 + 'SvgUtilService', 'Topo2DialogService',
230 + function (_$log_, _$loc_, _wss_, _ps_, _ms_, _sus_, _t2ds_) {
231 +
232 + $log = _$log_;
233 + $loc = _$loc_;
234 + wss = _wss_;
235 + ps = _ps_;
236 + ms = _ms_;
237 + sus = _sus_;
238 + t2ds = _t2ds_;
239 +
240 + messageHandlers = {
241 + mapSelectorResponse: handleMapResponse
242 + };
243 +
244 + return {
245 + init: init,
246 + openMapSelection: openMapSelection,
247 + toggle: toggle,
248 + stop: stop
249 + };
250 + }
251 + ]);
252 +
253 +})();
...@@ -75,6 +75,9 @@ ...@@ -75,6 +75,9 @@
75 nodeType: 'sub-region', 75 nodeType: 'sub-region',
76 mapDeviceTypeToGlyph: mapDeviceTypeToGlyph, 76 mapDeviceTypeToGlyph: mapDeviceTypeToGlyph,
77 onClick: function () { 77 onClick: function () {
78 +
79 + if (d3.event.defaultPrevented) return;
80 +
78 wss.sendEvent('topo2navRegion', { 81 wss.sendEvent('topo2navRegion', {
79 dir: 'down', 82 dir: 'down',
80 rid: this.get('id') 83 rid: this.get('id')
......
...@@ -130,6 +130,7 @@ ...@@ -130,6 +130,7 @@
130 <script src="app/view/topo2/topo2Breadcrumb.js"></script> 130 <script src="app/view/topo2/topo2Breadcrumb.js"></script>
131 <script src="app/view/topo2/topo2Collection.js"></script> 131 <script src="app/view/topo2/topo2Collection.js"></script>
132 <script src="app/view/topo2/topo2D3.js"></script> 132 <script src="app/view/topo2/topo2D3.js"></script>
133 + <script src="app/view/topo2/topo2Dialog.js"></script>
133 <script src="app/view/topo2/topo2Device.js"></script> 134 <script src="app/view/topo2/topo2Device.js"></script>
134 <script src="app/view/topo2/topo2Event.js"></script> 135 <script src="app/view/topo2/topo2Event.js"></script>
135 <script src="app/view/topo2/topo2Force.js"></script> 136 <script src="app/view/topo2/topo2Force.js"></script>
...@@ -138,6 +139,7 @@ ...@@ -138,6 +139,7 @@
138 <script src="app/view/topo2/topo2KeyCommands.js"></script> 139 <script src="app/view/topo2/topo2KeyCommands.js"></script>
139 <script src="app/view/topo2/topo2Layout.js"></script> 140 <script src="app/view/topo2/topo2Layout.js"></script>
140 <script src="app/view/topo2/topo2Link.js"></script> 141 <script src="app/view/topo2/topo2Link.js"></script>
142 + <script src="app/view/topo2/topo2Map.js"></script>
141 <script src="app/view/topo2/topo2Model.js"></script> 143 <script src="app/view/topo2/topo2Model.js"></script>
142 <script src="app/view/topo2/topo2NodeModel.js"></script> 144 <script src="app/view/topo2/topo2NodeModel.js"></script>
143 <script src="app/view/topo2/topo2Prefs.js"></script> 145 <script src="app/view/topo2/topo2Prefs.js"></script>
......