blob: 242d55a0c8d27de17e51a707982411991a974bb3 [file] [log] [blame]
Steven Burrows9edc7e02016-08-29 11:52:07 +01001/*
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 Select Module.
19 */
20
21(function () {
22 'use strict';
23
Steven Burrowsbd402842017-03-08 21:30:38 +000024 var t2rs, t2zs;
Steven Burrowsaf96a212016-12-28 12:57:02 +000025
Steven Burrows9edc7e02016-08-29 11:52:07 +010026 // internal state
Steven Burrowsaf96a212016-12-28 12:57:02 +000027 var consumeClick,
28 zoomer,
29 previousNearestLink; // previous link to mouse position
30
Steven Burrowsbd402842017-03-08 21:30:38 +000031 function init(svg) {
32 zoomer = t2zs.getZoomer();
Steven Burrowsaf96a212016-12-28 12:57:02 +000033 svg.on('mousemove', mouseMoveHandler);
34 svg.on('click', mouseClickHandler);
35 }
Steven Burrows9edc7e02016-08-29 11:52:07 +010036
Steven Burrowsdfa52b02016-09-02 13:50:43 +010037 function selectObject(obj) {}
Steven Burrows9edc7e02016-08-29 11:52:07 +010038
39 function clickConsumed(x) {
40 var cc = consumeClick;
Steven Burrowsdfa52b02016-09-02 13:50:43 +010041 consumeClick = Boolean(x);
Steven Burrows9edc7e02016-08-29 11:52:07 +010042 return cc;
43 }
44
Steven Burrowsaf96a212016-12-28 12:57:02 +000045 function mouseClickHandler() {
46
47 if (!d3.event.shiftKey) {
48 t2rs.deselectLink();
49 }
50
51 if (!clickConsumed()) {
52 if (previousNearestLink) {
53 previousNearestLink.select();
54 }
55 }
56
57 }
58
59 // Select Links
60 function mouseMoveHandler() {
61 var mp = getLogicalMousePosition(this),
62 link = computeNearestLink(mp);
63
Steven Burrowsaf96a212016-12-28 12:57:02 +000064 if (link) {
65 if (previousNearestLink && previousNearestLink !== link) {
66 previousNearestLink.unenhance();
67 }
68 link.enhance();
69 } else if (previousNearestLink) {
70 previousNearestLink.unenhance();
71 }
72
73 previousNearestLink = link;
74 }
75
76 function getLogicalMousePosition(container) {
77 var m = d3.mouse(container),
78 sc = zoomer.scale(),
79 tr = zoomer.translate(),
80 mx = (m[0] - tr[0]) / sc,
81 my = (m[1] - tr[1]) / sc;
82 return { x: mx, y: my };
83 }
84
85 function sq(x) {
86 return x * x;
87 }
88
89 function mdist(p, m) {
90 return Math.sqrt(sq(p.x - m.x) + sq(p.y - m.y));
91 }
92
93 function prox(dist) {
94 return dist / zoomer.scale();
95 }
96
97 function computeNearestLink(mouse) {
98 var proximity = prox(30),
99 nearest = null,
100 minDist;
101
102 function pdrop(line, mouse) {
103 var x1 = line.x1,
104 y1 = line.y1,
105 x2 = line.x2,
106 y2 = line.y2,
107 x3 = mouse.x,
108 y3 = mouse.y,
109 k = ((y2 - y1) * (x3 - x1) - (x2 - x1) * (y3 - y1)) /
110 (sq(y2 - y1) + sq(x2 - x1)),
111 x4 = x3 - k * (y2 - y1),
112 y4 = y3 + k * (x2 - x1);
113 return { x: x4, y: y4 };
114 }
115
116 function lineHit(line, p, m) {
117 if (p.x < line.x1 && p.x < line.x2) return false;
118 if (p.x > line.x1 && p.x > line.x2) return false;
119 if (p.y < line.y1 && p.y < line.y2) return false;
120 if (p.y > line.y1 && p.y > line.y2) return false;
121 // line intersects, but are we close enough?
122 return mdist(p, m) <= proximity;
123 }
124
Steven Burrowsb11a8b82017-03-10 16:00:31 +0000125 var links = [];
126
127 if (t2rs.model.get('links')) {
128 links = (t2rs.backgroundRendered) ? t2rs.regionLinks() : [];
129 }
Steven Burrowsaf96a212016-12-28 12:57:02 +0000130
131 if (links.length) {
132 minDist = proximity * 2;
133
134 links.forEach(function (d) {
135 var line = d.get('position'),
136 point,
137 hit,
138 dist;
139
140 // TODO: Reinstate when showHost() is implemented
141 // if (!api.showHosts() && d.type() === 'hostLink') {
142 // return; // skip hidden host links
143 // }
144
145 if (line) {
146 point = pdrop(line, mouse);
147 hit = lineHit(line, point, mouse);
148 if (hit) {
149 dist = mdist(point, mouse);
150 if (dist < minDist) {
151 minDist = dist;
152 nearest = d;
153 }
154 }
155 }
156 });
157 }
158
159 return nearest;
160 }
161
Steven Burrows9edc7e02016-08-29 11:52:07 +0100162 angular.module('ovTopo2')
Steven Burrowsdfa52b02016-09-02 13:50:43 +0100163 .factory('Topo2SelectService', [
Steven Burrowsbd402842017-03-08 21:30:38 +0000164 'Topo2RegionService', 'Topo2ZoomService',
165 function (_t2rs_, _t2zs_) {
Steven Burrowsaf96a212016-12-28 12:57:02 +0000166
167 t2rs = _t2rs_;
Steven Burrowsbd402842017-03-08 21:30:38 +0000168 t2zs = _t2zs_;
Steven Burrows9edc7e02016-08-29 11:52:07 +0100169
170 return {
Steven Burrowsaf96a212016-12-28 12:57:02 +0000171 init: init,
Steven Burrows9edc7e02016-08-29 11:52:07 +0100172 selectObject: selectObject,
173 clickConsumed: clickConsumed
174 };
175 }
176 ]);
177
178})();