blob: 779e408aebf7c16ab2fda10e2818a7d6c511202e [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 Hunt08f841d02015-02-10 14:39:20 -080064 if (hovered != m) {
65 hovered = m;
Simon Hunt584e92d2015-08-24 11:27:22 -070066 tov.hooks.mouseOver({
67 id: m.id,
68 class: m.class,
69 type: m.type
70 });
Simon Hunt08f841d02015-02-10 14:39:20 -080071 }
72 }
73 }
74
75 function nodeMouseOut(m) {
76 if (!m.dragStarted) {
77 if (hovered) {
78 hovered = null;
Simon Hunt584e92d2015-08-24 11:27:22 -070079 tov.hooks.mouseOut();
Simon Hunt08f841d02015-02-10 14:39:20 -080080 }
Simon Hunt08f841d02015-02-10 14:39:20 -080081 }
82 }
83
84 // ==========================
85
86 function selectObject(obj) {
87 var el = this,
Simon Hunt5aac2fc2015-06-09 12:34:07 -070088 nodeEv = el && el.tagName === 'g',
89 ev = d3.event.sourceEvent || {},
Simon Hunt08f841d02015-02-10 14:39:20 -080090 n;
91
92 if (api.zoomingOrPanning(ev)) {
93 return;
94 }
95
Simon Hunt5aac2fc2015-06-09 12:34:07 -070096 if (nodeEv) {
Simon Hunt08f841d02015-02-10 14:39:20 -080097 n = d3.select(el);
98 } else {
99 api.node().each(function (d) {
100 if (d == obj) {
101 n = d3.select(el = this);
102 }
103 });
104 }
105 if (!n) return;
106
Simon Hunt5aac2fc2015-06-09 12:34:07 -0700107 if (nodeEv) {
108 consumeClick = true;
109 }
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700110 api.deselectLink();
111
Simon Hunt08f841d02015-02-10 14:39:20 -0800112 if (ev.shiftKey && n.classed('selected')) {
113 deselectObject(obj.id);
114 updateDetail();
115 return;
116 }
117
118 if (!ev.shiftKey) {
Simon Hunta17fa672015-08-19 18:42:22 -0700119 deselectAll(true);
Simon Hunt08f841d02015-02-10 14:39:20 -0800120 }
121
122 selections[obj.id] = { obj: obj, el: el };
123 selectOrder.push(obj.id);
124
125 n.classed('selected', true);
126 api.updateDeviceColors(obj);
127 updateDetail();
Simon Hunt08f841d02015-02-10 14:39:20 -0800128 }
129
130 function deselectObject(id) {
131 var obj = selections[id];
132 if (obj) {
133 d3.select(obj.el).classed('selected', false);
134 delete selections[id];
135 fs.removeFromArray(id, selectOrder);
136 api.updateDeviceColors(obj.obj);
137 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800138 }
139
Simon Hunta17fa672015-08-19 18:42:22 -0700140 function deselectAll(skipUpdate) {
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700141 var something = (selectOrder.length > 0);
142
Simon Hunt08f841d02015-02-10 14:39:20 -0800143 // deselect all nodes in the network...
144 api.node().classed('selected', false);
145 selections = {};
146 selectOrder = [];
147 api.updateDeviceColors();
Simon Hunta17fa672015-08-19 18:42:22 -0700148 if (!skipUpdate) {
149 updateDetail();
150 }
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700151
152 // return true if something was selected
153 return something;
Simon Hunt08f841d02015-02-10 14:39:20 -0800154 }
155
156 // === -----------------------------------------------------
157
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700158 function requestDetails(data) {
Simon Hunt237676b52015-03-10 19:04:26 -0700159 wss.sendEvent('requestDetails', {
Simon Hunt08f841d02015-02-10 14:39:20 -0800160 id: data.id,
161 class: data.class
162 });
163 }
164
165 // === -----------------------------------------------------
166
167 function updateDetail() {
168 var nSel = selectOrder.length;
169 if (!nSel) {
170 emptySelect();
171 } else if (nSel === 1) {
172 singleSelect();
173 } else {
174 multiSelect();
175 }
176 }
177
178 function emptySelect() {
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700179 tov.hooks.emptySelect();
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700180 tps.displayNothing();
Simon Hunt08f841d02015-02-10 14:39:20 -0800181 }
182
183 function singleSelect() {
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700184 var data = getSel(0).obj;
185 requestDetails(data);
186 // NOTE: detail panel is shown as a response to receiving
187 // a 'showDetails' event from the server. See 'showDetails'
188 // callback function below...
Simon Hunt08f841d02015-02-10 14:39:20 -0800189 }
190
191 function multiSelect() {
Simon Hunt08f841d02015-02-10 14:39:20 -0800192 // display the selected nodes in the detail panel
193 tps.displayMulti(selectOrder);
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700194 addHostSelectionActions();
195 tov.hooks.multiSelect(selectOrder);
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700196 tps.displaySomething();
Simon Hunt08f841d02015-02-10 14:39:20 -0800197 }
198
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700199 function addHostSelectionActions() {
200 if (allSelectionsClass('host')) {
201 if (nSel() === 2) {
202 tps.addAction({
203 id: 'host-flow-btn',
204 gid: 'endstation',
205 cb: tts.addHostIntent,
206 tt: 'Create Host-to-Host Flow'
207 });
208 } else if (nSel() >= 2) {
209 tps.addAction({
210 id: 'mult-src-flow-btn',
211 gid: 'flows',
212 cb: tts.addMultiSourceIntent,
213 tt: 'Create Multi-Source Flow'
214 });
215 }
216 }
217 }
218
Simon Hunt08f841d02015-02-10 14:39:20 -0800219
220 // === -----------------------------------------------------
221 // Event Handlers
222
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700223 // display the data for the single selected node
Simon Hunt08f841d02015-02-10 14:39:20 -0800224 function showDetails(data) {
Simon Hunt3a0598f2015-08-04 19:59:04 -0700225 var buttons = fs.isA(data.buttons) || [];
Simon Hunt08f841d02015-02-10 14:39:20 -0800226 tps.displaySingle(data);
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700227 tov.installButtons(buttons, data, data.props['URI']);
228 tov.hooks.singleSelect(data);
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700229 tps.displaySomething();
Simon Hunt6036b192015-02-11 11:20:26 -0800230 }
231
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700232 // returns true if we are hovering over a node, or any nodes are selected
233 function somethingSelected() {
234 return hovered || nSel();
Simon Hunt08f841d02015-02-10 14:39:20 -0800235 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800236
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700237 function clickConsumed(x) {
238 var cc = consumeClick;
239 consumeClick = !!x;
240 return cc;
241 }
242
Simon Hunt08f841d02015-02-10 14:39:20 -0800243 // === -----------------------------------------------------
244 // === MODULE DEFINITION ===
245
246 angular.module('ovTopo')
Simon Hunt75ec9692015-02-11 16:40:36 -0800247 .factory('TopoSelectService',
Simon Huntfb940112015-07-29 18:36:35 -0700248 ['$log', 'FnService', 'WebSocketService', 'TopoOverlayService',
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700249 'TopoPanelService', 'TopoTrafficService', 'NavService',
Simon Hunt08f841d02015-02-10 14:39:20 -0800250
Simon Huntfb940112015-07-29 18:36:35 -0700251 function (_$log_, _fs_, _wss_, _tov_, _tps_, _tts_, _ns_) {
Simon Hunt6036b192015-02-11 11:20:26 -0800252 $log = _$log_;
253 fs = _fs_;
Simon Hunt237676b52015-03-10 19:04:26 -0700254 wss = _wss_;
Simon Huntfb940112015-07-29 18:36:35 -0700255 tov = _tov_;
Simon Hunt6036b192015-02-11 11:20:26 -0800256 tps = _tps_;
Simon Huntf542d842015-02-11 16:20:33 -0800257 tts = _tts_;
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700258 ns = _ns_;
Simon Hunt08f841d02015-02-10 14:39:20 -0800259
Simon Hunt6036b192015-02-11 11:20:26 -0800260 function initSelect(_api_) {
261 api = _api_;
262 }
Simon Hunt08f841d02015-02-10 14:39:20 -0800263
Simon Hunt6036b192015-02-11 11:20:26 -0800264 function destroySelect() { }
Simon Hunt08f841d02015-02-10 14:39:20 -0800265
Simon Hunt6036b192015-02-11 11:20:26 -0800266 return {
267 initSelect: initSelect,
268 destroySelect: destroySelect,
Simon Hunt08f841d02015-02-10 14:39:20 -0800269
Simon Hunt6036b192015-02-11 11:20:26 -0800270 showDetails: showDetails,
Simon Hunt08f841d02015-02-10 14:39:20 -0800271
Simon Hunt6036b192015-02-11 11:20:26 -0800272 nodeMouseOver: nodeMouseOver,
273 nodeMouseOut: nodeMouseOut,
274 selectObject: selectObject,
275 deselectObject: deselectObject,
276 deselectAll: deselectAll,
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700277 updateDetail: updateDetail,
Simon Huntf542d842015-02-11 16:20:33 -0800278
Simon Hunta0eb0a82015-02-11 12:30:06 -0800279 hovered: function () { return hovered; },
Simon Huntf542d842015-02-11 16:20:33 -0800280 selectOrder: function () { return selectOrder; },
Simon Hunt8d22c4b2015-08-06 16:24:43 -0700281 somethingSelected: somethingSelected,
Simon Hunt0c6b2d32015-03-26 17:46:29 -0700282
283 clickConsumed: clickConsumed
Simon Hunt6036b192015-02-11 11:20:26 -0800284 };
285 }]);
Simon Hunt08f841d02015-02-10 14:39:20 -0800286}());