blob: 44fd14abdb1ee56aa7894d9aa61624734d8a0ef5 [file] [log] [blame]
Simon Hunt08f841d02015-02-10 14:39:20 -08001/*
2 * Copyright 2015 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 Selection Module.
19 Defines behavior when selecting nodes.
20 */
21
22(function () {
23 'use strict';
24
25 // injected refs
Simon Hunt0c6b2d32015-03-26 17:46:29 -070026 var $log, fs, wss, tps, tts;
Simon Hunt08f841d02015-02-10 14:39:20 -080027
28 // api to topoForce
29 var api;
30 /*
31 node() // get ref to D3 selection of nodes
32 zoomingOrPanning( ev )
33 updateDeviceColors( [dev] )
Simon Hunt0c6b2d32015-03-26 17:46:29 -070034 deselectLink()
Simon Hunt08f841d02015-02-10 14:39:20 -080035 */
36
37 // internal state
38 var hovered, // the node over which the mouse is hovering
39 selections = {}, // currently selected nodes (by id)
40 selectOrder = [], // the order in which we made selections
Simon Hunt0c6b2d32015-03-26 17:46:29 -070041 consumeClick = false; // used to coordinate with SVG click handler
Simon Hunt08f841d02015-02-10 14:39:20 -080042
43 // ==========================
44
45 function nSel() {
46 return selectOrder.length;
47 }
48 function getSel(idx) {
49 return selections[selectOrder[idx]];
50 }
51 function allSelectionsClass(cls) {
52 for (var i=0, n=nSel(); i<n; i++) {
53 if (getSel(i).obj.class !== cls) {
54 return false;
55 }
56 }
57 return true;
58 }
59
60 // ==========================
61
62 function nodeMouseOver(m) {
63 if (!m.dragStarted) {
Simon Hunt36a58c62015-04-08 11:00:07 -070064 //$log.debug("MouseOver()...", m);
Simon Hunt08f841d02015-02-10 14:39:20 -080065 if (hovered != m) {
66 hovered = m;
Simon Huntf542d842015-02-11 16:20:33 -080067 tts.requestTrafficForMode();
Simon Hunt08f841d02015-02-10 14:39:20 -080068 }
69 }
70 }
71
72 function nodeMouseOut(m) {
73 if (!m.dragStarted) {
74 if (hovered) {
75 hovered = null;
Simon Huntf542d842015-02-11 16:20:33 -080076 tts.requestTrafficForMode();
Simon Hunt08f841d02015-02-10 14:39:20 -080077 }
Simon Hunt36a58c62015-04-08 11:00:07 -070078 //$log.debug("MouseOut()...", m);
Simon Hunt08f841d02015-02-10 14:39:20 -080079 }
80 }
81
82 // ==========================
83
84 function selectObject(obj) {
85 var el = this,
86 ev = d3.event.sourceEvent,
87 n;
88
89 if (api.zoomingOrPanning(ev)) {
90 return;
91 }
92
93 if (el) {
94 n = d3.select(el);
95 } else {
96 api.node().each(function (d) {
97 if (d == obj) {
98 n = d3.select(el = this);
99 }
100 });
101 }
102 if (!n) return;
103
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700104 consumeClick = true;
105 api.deselectLink();
106
Simon Hunt08f841d02015-02-10 14:39:20 -0800107 if (ev.shiftKey && n.classed('selected')) {
108 deselectObject(obj.id);
109 updateDetail();
110 return;
111 }
112
113 if (!ev.shiftKey) {
114 deselectAll();
115 }
116
117 selections[obj.id] = { obj: obj, el: el };
118 selectOrder.push(obj.id);
119
120 n.classed('selected', true);
121 api.updateDeviceColors(obj);
122 updateDetail();
Simon Hunt08f841d02015-02-10 14:39:20 -0800123 }
124
125 function deselectObject(id) {
126 var obj = selections[id];
127 if (obj) {
128 d3.select(obj.el).classed('selected', false);
129 delete selections[id];
130 fs.removeFromArray(id, selectOrder);
131 api.updateDeviceColors(obj.obj);
132 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800133 }
134
135 function deselectAll() {
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700136 var something = (selectOrder.length > 0);
137
Simon Hunt08f841d02015-02-10 14:39:20 -0800138 // deselect all nodes in the network...
139 api.node().classed('selected', false);
140 selections = {};
141 selectOrder = [];
142 api.updateDeviceColors();
143 updateDetail();
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700144
145 // return true if something was selected
146 return something;
Simon Hunt08f841d02015-02-10 14:39:20 -0800147 }
148
149 // === -----------------------------------------------------
150
151 function requestDetails() {
152 var data = getSel(0).obj;
Simon Hunt237676b52015-03-10 19:04:26 -0700153 wss.sendEvent('requestDetails', {
Simon Hunt08f841d02015-02-10 14:39:20 -0800154 id: data.id,
155 class: data.class
156 });
157 }
158
159 // === -----------------------------------------------------
160
161 function updateDetail() {
162 var nSel = selectOrder.length;
163 if (!nSel) {
164 emptySelect();
165 } else if (nSel === 1) {
166 singleSelect();
167 } else {
168 multiSelect();
169 }
170 }
171
172 function emptySelect() {
Simon Huntf542d842015-02-11 16:20:33 -0800173 tts.cancelTraffic();
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700174 tps.displayNothing();
Simon Hunt08f841d02015-02-10 14:39:20 -0800175 }
176
177 function singleSelect() {
178 // NOTE: detail is shown from 'showDetails' event callback
179 requestDetails();
Simon Huntf542d842015-02-11 16:20:33 -0800180 tts.cancelTraffic();
181 tts.requestTrafficForMode();
Simon Hunt08f841d02015-02-10 14:39:20 -0800182 }
183
184 function multiSelect() {
Simon Hunt08f841d02015-02-10 14:39:20 -0800185 // display the selected nodes in the detail panel
186 tps.displayMulti(selectOrder);
187
188 // always add the 'show traffic' action
Bri Prebilic Colef5e48b12015-04-21 14:52:36 -0700189 tps.addAction({
190 id: '-mult-rel-traf-btn',
191 gid: 'allTraffic',
192 cb: tts.showRelatedIntentsAction,
193 tt: 'Show Related Traffic'
194 });
Simon Hunt08f841d02015-02-10 14:39:20 -0800195
196 // add other actions, based on what is selected...
197 if (nSel() === 2 && allSelectionsClass('host')) {
Bri Prebilic Colef5e48b12015-04-21 14:52:36 -0700198 tps.addAction({
199 id: 'host-flow-btn',
200 gid: 'endstation',
201 cb: tts.addHostIntentAction,
202 tt: 'Create Host-to-Host Flow'
203 });
Simon Hunt08f841d02015-02-10 14:39:20 -0800204 } else if (nSel() >= 2 && allSelectionsClass('host')) {
Bri Prebilic Colef5e48b12015-04-21 14:52:36 -0700205 tps.addAction({
206 id: 'mult-src-flow-btn',
207 gid: 'flows',
208 cb: tts.addMultiSourceIntentAction,
209 tt: 'Create Multi-Source Flow'
210 });
Simon Hunt08f841d02015-02-10 14:39:20 -0800211 }
212
Simon Huntf542d842015-02-11 16:20:33 -0800213 tts.cancelTraffic();
214 tts.requestTrafficForMode();
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700215 tps.displaySomething();
Simon Hunt08f841d02015-02-10 14:39:20 -0800216 }
217
218
219 // === -----------------------------------------------------
220 // Event Handlers
221
222 function showDetails(data) {
Simon Hunt08f841d02015-02-10 14:39:20 -0800223 // display the data for the single selected node
224 tps.displaySingle(data);
225
226 // always add the 'show traffic' action
Bri Prebilic Colef5e48b12015-04-21 14:52:36 -0700227 tps.addAction({
228 id: '-sin-rel-traf-btn',
229 gid: 'intentTraffic',
230 cb: tts.showRelatedIntentsAction,
231 tt: 'Show Related Traffic'
232 });
Simon Hunt08f841d02015-02-10 14:39:20 -0800233
234 // add other actions, based on what is selected...
235 if (data.type === 'switch') {
Bri Prebilic Colef5e48b12015-04-21 14:52:36 -0700236 tps.addAction({
237 id: 'sin-dev-flows-btn',
238 gid: 'flows',
239 cb: tts.showDeviceLinkFlowsAction,
240 tt: 'Show Device Flows'
241 });
Simon Hunt08f841d02015-02-10 14:39:20 -0800242 }
243
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700244 tps.displaySomething();
Simon Hunt6036b192015-02-11 11:20:26 -0800245 }
246
Simon Huntf542d842015-02-11 16:20:33 -0800247 function validateSelectionContext() {
248 if (!hovered && !nSel()) {
249 tts.cancelTraffic();
250 return false;
251 }
252 return true;
Simon Hunt08f841d02015-02-10 14:39:20 -0800253 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800254
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700255 function clickConsumed(x) {
256 var cc = consumeClick;
257 consumeClick = !!x;
258 return cc;
259 }
260
Simon Hunt08f841d02015-02-10 14:39:20 -0800261 // === -----------------------------------------------------
262 // === MODULE DEFINITION ===
263
264 angular.module('ovTopo')
Simon Hunt75ec9692015-02-11 16:40:36 -0800265 .factory('TopoSelectService',
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700266 ['$log', 'FnService', 'WebSocketService',
Simon Hunt237676b52015-03-10 19:04:26 -0700267 'TopoPanelService', 'TopoTrafficService',
Simon Hunt08f841d02015-02-10 14:39:20 -0800268
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700269 function (_$log_, _fs_, _wss_, _tps_, _tts_) {
Simon Hunt6036b192015-02-11 11:20:26 -0800270 $log = _$log_;
271 fs = _fs_;
Simon Hunt237676b52015-03-10 19:04:26 -0700272 wss = _wss_;
Simon Hunt6036b192015-02-11 11:20:26 -0800273 tps = _tps_;
Simon Huntf542d842015-02-11 16:20:33 -0800274 tts = _tts_;
Simon Hunt08f841d02015-02-10 14:39:20 -0800275
Simon Hunt6036b192015-02-11 11:20:26 -0800276 function initSelect(_api_) {
277 api = _api_;
278 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800279
Simon Hunt6036b192015-02-11 11:20:26 -0800280 function destroySelect() { }
Simon Hunt08f841d02015-02-10 14:39:20 -0800281
Simon Hunt6036b192015-02-11 11:20:26 -0800282 return {
283 initSelect: initSelect,
284 destroySelect: destroySelect,
Simon Hunt08f841d02015-02-10 14:39:20 -0800285
Simon Hunt6036b192015-02-11 11:20:26 -0800286 showDetails: showDetails,
Simon Hunt08f841d02015-02-10 14:39:20 -0800287
Simon Hunt6036b192015-02-11 11:20:26 -0800288 nodeMouseOver: nodeMouseOver,
289 nodeMouseOut: nodeMouseOut,
290 selectObject: selectObject,
291 deselectObject: deselectObject,
292 deselectAll: deselectAll,
Simon Huntf542d842015-02-11 16:20:33 -0800293
Simon Hunta0eb0a82015-02-11 12:30:06 -0800294 hovered: function () { return hovered; },
Simon Huntf542d842015-02-11 16:20:33 -0800295 selectOrder: function () { return selectOrder; },
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700296 validateSelectionContext: validateSelectionContext,
297
298 clickConsumed: clickConsumed
Simon Hunt6036b192015-02-11 11:20:26 -0800299 };
300 }]);
Simon Hunt08f841d02015-02-10 14:39:20 -0800301}());