blob: 72a689f60af3cd680b4240c004ca8806feba38fb [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 Huntfb940112015-07-29 18:36:35 -070026 var $log, fs, wss, tov, tps, tts, ns;
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,
Simon Hunt5aac2fc2015-06-09 12:34:07 -070086 nodeEv = el && el.tagName === 'g',
87 ev = d3.event.sourceEvent || {},
Simon Hunt08f841d02015-02-10 14:39:20 -080088 n;
89
90 if (api.zoomingOrPanning(ev)) {
91 return;
92 }
93
Simon Hunt5aac2fc2015-06-09 12:34:07 -070094 if (nodeEv) {
Simon Hunt08f841d02015-02-10 14:39:20 -080095 n = d3.select(el);
96 } else {
97 api.node().each(function (d) {
98 if (d == obj) {
99 n = d3.select(el = this);
100 }
101 });
102 }
103 if (!n) return;
104
Simon Hunt5aac2fc2015-06-09 12:34:07 -0700105 if (nodeEv) {
106 consumeClick = true;
107 }
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700108 api.deselectLink();
109
Simon Hunt08f841d02015-02-10 14:39:20 -0800110 if (ev.shiftKey && n.classed('selected')) {
111 deselectObject(obj.id);
112 updateDetail();
113 return;
114 }
115
116 if (!ev.shiftKey) {
Simon Hunta17fa672015-08-19 18:42:22 -0700117 deselectAll(true);
Simon Hunt08f841d02015-02-10 14:39:20 -0800118 }
119
120 selections[obj.id] = { obj: obj, el: el };
121 selectOrder.push(obj.id);
122
123 n.classed('selected', true);
124 api.updateDeviceColors(obj);
125 updateDetail();
Simon Hunt08f841d02015-02-10 14:39:20 -0800126 }
127
128 function deselectObject(id) {
129 var obj = selections[id];
130 if (obj) {
131 d3.select(obj.el).classed('selected', false);
132 delete selections[id];
133 fs.removeFromArray(id, selectOrder);
134 api.updateDeviceColors(obj.obj);
135 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800136 }
137
Simon Hunta17fa672015-08-19 18:42:22 -0700138 function deselectAll(skipUpdate) {
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700139 var something = (selectOrder.length > 0);
140
Simon Hunt08f841d02015-02-10 14:39:20 -0800141 // deselect all nodes in the network...
142 api.node().classed('selected', false);
143 selections = {};
144 selectOrder = [];
145 api.updateDeviceColors();
Simon Hunta17fa672015-08-19 18:42:22 -0700146 if (!skipUpdate) {
147 updateDetail();
148 }
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700149
150 // return true if something was selected
151 return something;
Simon Hunt08f841d02015-02-10 14:39:20 -0800152 }
153
154 // === -----------------------------------------------------
155
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700156 function requestDetails(data) {
Simon Hunt237676b52015-03-10 19:04:26 -0700157 wss.sendEvent('requestDetails', {
Simon Hunt08f841d02015-02-10 14:39:20 -0800158 id: data.id,
159 class: data.class
160 });
161 }
162
163 // === -----------------------------------------------------
164
165 function updateDetail() {
166 var nSel = selectOrder.length;
167 if (!nSel) {
168 emptySelect();
169 } else if (nSel === 1) {
170 singleSelect();
171 } else {
172 multiSelect();
173 }
174 }
175
176 function emptySelect() {
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700177 tov.hooks.emptySelect();
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700178 tps.displayNothing();
Simon Hunt08f841d02015-02-10 14:39:20 -0800179 }
180
181 function singleSelect() {
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700182 var data = getSel(0).obj;
183 requestDetails(data);
184 // NOTE: detail panel is shown as a response to receiving
185 // a 'showDetails' event from the server. See 'showDetails'
186 // callback function below...
Simon Hunt08f841d02015-02-10 14:39:20 -0800187 }
188
189 function multiSelect() {
Simon Hunt08f841d02015-02-10 14:39:20 -0800190 // display the selected nodes in the detail panel
191 tps.displayMulti(selectOrder);
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700192 addHostSelectionActions();
193 tov.hooks.multiSelect(selectOrder);
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700194 tps.displaySomething();
Simon Hunt08f841d02015-02-10 14:39:20 -0800195 }
196
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700197 function addHostSelectionActions() {
198 if (allSelectionsClass('host')) {
199 if (nSel() === 2) {
200 tps.addAction({
201 id: 'host-flow-btn',
202 gid: 'endstation',
203 cb: tts.addHostIntent,
204 tt: 'Create Host-to-Host Flow'
205 });
206 } else if (nSel() >= 2) {
207 tps.addAction({
208 id: 'mult-src-flow-btn',
209 gid: 'flows',
210 cb: tts.addMultiSourceIntent,
211 tt: 'Create Multi-Source Flow'
212 });
213 }
214 }
215 }
216
Simon Hunt08f841d02015-02-10 14:39:20 -0800217
218 // === -----------------------------------------------------
219 // Event Handlers
220
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700221 // display the data for the single selected node
Simon Hunt08f841d02015-02-10 14:39:20 -0800222 function showDetails(data) {
Simon Hunt3a0598f2015-08-04 19:59:04 -0700223 var buttons = fs.isA(data.buttons) || [];
Simon Hunt08f841d02015-02-10 14:39:20 -0800224 tps.displaySingle(data);
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700225 tov.installButtons(buttons, data, data.props['URI']);
226 tov.hooks.singleSelect(data);
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700227 tps.displaySomething();
Simon Hunt6036b192015-02-11 11:20:26 -0800228 }
229
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700230 // returns true if we are hovering over a node, or any nodes are selected
231 function somethingSelected() {
232 return hovered || nSel();
Simon Hunt08f841d02015-02-10 14:39:20 -0800233 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800234
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700235 function clickConsumed(x) {
236 var cc = consumeClick;
237 consumeClick = !!x;
238 return cc;
239 }
240
Simon Hunt08f841d02015-02-10 14:39:20 -0800241 // === -----------------------------------------------------
242 // === MODULE DEFINITION ===
243
244 angular.module('ovTopo')
Simon Hunt75ec9692015-02-11 16:40:36 -0800245 .factory('TopoSelectService',
Simon Huntfb940112015-07-29 18:36:35 -0700246 ['$log', 'FnService', 'WebSocketService', 'TopoOverlayService',
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700247 'TopoPanelService', 'TopoTrafficService', 'NavService',
Simon Hunt08f841d02015-02-10 14:39:20 -0800248
Simon Huntfb940112015-07-29 18:36:35 -0700249 function (_$log_, _fs_, _wss_, _tov_, _tps_, _tts_, _ns_) {
Simon Hunt6036b192015-02-11 11:20:26 -0800250 $log = _$log_;
251 fs = _fs_;
Simon Hunt237676b52015-03-10 19:04:26 -0700252 wss = _wss_;
Simon Huntfb940112015-07-29 18:36:35 -0700253 tov = _tov_;
Simon Hunt6036b192015-02-11 11:20:26 -0800254 tps = _tps_;
Simon Huntf542d842015-02-11 16:20:33 -0800255 tts = _tts_;
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700256 ns = _ns_;
Simon Hunt08f841d02015-02-10 14:39:20 -0800257
Simon Hunt6036b192015-02-11 11:20:26 -0800258 function initSelect(_api_) {
259 api = _api_;
260 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800261
Simon Hunt6036b192015-02-11 11:20:26 -0800262 function destroySelect() { }
Simon Hunt08f841d02015-02-10 14:39:20 -0800263
Simon Hunt6036b192015-02-11 11:20:26 -0800264 return {
265 initSelect: initSelect,
266 destroySelect: destroySelect,
Simon Hunt08f841d02015-02-10 14:39:20 -0800267
Simon Hunt6036b192015-02-11 11:20:26 -0800268 showDetails: showDetails,
Simon Hunt08f841d02015-02-10 14:39:20 -0800269
Simon Hunt6036b192015-02-11 11:20:26 -0800270 nodeMouseOver: nodeMouseOver,
271 nodeMouseOut: nodeMouseOut,
272 selectObject: selectObject,
273 deselectObject: deselectObject,
274 deselectAll: deselectAll,
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700275 updateDetail: updateDetail,
Simon Huntf542d842015-02-11 16:20:33 -0800276
Simon Hunta0eb0a82015-02-11 12:30:06 -0800277 hovered: function () { return hovered; },
Simon Huntf542d842015-02-11 16:20:33 -0800278 selectOrder: function () { return selectOrder; },
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700279 somethingSelected: somethingSelected,
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700280
281 clickConsumed: clickConsumed
Simon Hunt6036b192015-02-11 11:20:26 -0800282 };
283 }]);
Simon Hunt08f841d02015-02-10 14:39:20 -0800284}());