blob: 1bdb96bab8b688bbf3120ed2c7afacf0d40df47e [file] [log] [blame]
Simon Hunt737c89f2015-01-28 12:23:19 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Simon Hunt737c89f2015-01-28 12:23:19 -08003 *
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 -- SVG -- Util Service
19 */
20
21/*
22 The SVG Util Service provides a miscellany of utility functions.
23 */
24
25(function () {
26 'use strict';
27
28 // injected references
29 var $log, fs;
30
Simon Huntf4ef6dd2016-02-03 17:05:14 -080031 // TODO: change 'force' ref to be 'force.alpha' ref.
32 function createDragBehavior(force, selectCb, atDragEnd,
Steven Burrows2b15ae72017-04-28 10:24:43 -040033 dragEnabled, clickEnabled, zs) {
Simon Huntf4ef6dd2016-02-03 17:05:14 -080034 var draggedThreshold = d3.scale.linear()
35 .domain([0, 0.1])
36 .range([5, 20])
37 .clamp(true),
38 drag,
39 fSel = fs.isF(selectCb),
40 fEnd = fs.isF(atDragEnd),
41 fDEn = fs.isF(dragEnabled),
42 fCEn = fs.isF(clickEnabled),
43 bad = [];
44
45 function naf(what) {
46 return 'SvgUtilService: createDragBehavior(): ' + what +
47 ' is not a function';
48 }
49
50 if (!force) {
51 bad.push('SvgUtilService: createDragBehavior(): ' +
52 'Bad force reference');
53 }
54 if (!fSel) {
55 bad.push(naf('selectCb'));
56 }
57 if (!fEnd) {
58 bad.push(naf('atDragEnd'));
59 }
60 if (!fDEn) {
61 bad.push(naf('dragEnabled'));
62 }
63 if (!fCEn) {
64 bad.push(naf('clickEnabled'));
65 }
66
67 if (bad.length) {
68 $log.error(bad.join('\n'));
69 return null;
70 }
71
72 function dragged(d) {
Steven Burrows2b15ae72017-04-28 10:24:43 -040073 var scale = zs ? zs.scale() : 1,
74 threshold = draggedThreshold(force.alpha()) / scale,
Simon Huntf4ef6dd2016-02-03 17:05:14 -080075 dx = d.oldX - d.px,
76 dy = d.oldY - d.py;
Steven Burrows2b15ae72017-04-28 10:24:43 -040077
Simon Huntf4ef6dd2016-02-03 17:05:14 -080078 if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
79 d.dragged = true;
80 }
81 return d.dragged;
82 }
83
84 drag = d3.behavior.drag()
Steven Burrows1c2a9682017-07-14 16:52:46 +010085 .origin(function (d) { return d; })
86 .on('dragstart', function (d) {
Simon Huntf4ef6dd2016-02-03 17:05:14 -080087 if (clickEnabled() || dragEnabled()) {
Simon Huntf4ef6dd2016-02-03 17:05:14 -080088 d.oldX = d.x;
89 d.oldY = d.y;
90 d.dragged = false;
91 d.fixed |= 2;
92 d.dragStarted = true;
93 }
94 })
Steven Burrows1c2a9682017-07-14 16:52:46 +010095 .on('drag', function (d) {
Simon Huntf4ef6dd2016-02-03 17:05:14 -080096 if (dragEnabled()) {
97 d.px = d3.event.x;
98 d.py = d3.event.y;
99 if (dragged(d)) {
100 if (!force.alpha()) {
101 force.alpha(.025);
102 }
103 }
104 }
105 })
Steven Burrows1c2a9682017-07-14 16:52:46 +0100106 .on('dragend', function (d) {
Steven Burrows2b15ae72017-04-28 10:24:43 -0400107 d3.event.sourceEvent.stopPropagation();
Steven Burrowse3a18842016-09-22 15:33:33 +0100108
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800109 if (d.dragStarted) {
110 d.dragStarted = false;
111 if (!dragged(d)) {
112 // consider this the same as a 'click'
113 // (selection of a node)
114 if (clickEnabled()) {
115 selectCb.call(this, d);
116 }
117 }
118 d.fixed &= ~6;
119
120 // hook at the end of a drag gesture
121 if (dragEnabled()) {
122 atDragEnd.call(this, d);
123 }
124 }
125 });
126
127 return drag;
128 }
129
130
131 function loadGlow(defs, r, g, b, id) {
132 var glow = defs.append('filter')
133 .attr('x', '-50%')
134 .attr('y', '-50%')
135 .attr('width', '200%')
136 .attr('height', '200%')
137 .attr('id', id);
138
139 glow.append('feColorMatrix')
140 .attr('type', 'matrix')
141 .attr('values',
142 '0 0 0 0 ' + r + ' ' +
143 '0 0 0 0 ' + g + ' ' +
144 '0 0 0 0 ' + b + ' ' +
145 '0 0 0 1 0 ');
146
147 glow.append('feGaussianBlur')
148 .attr('stdDeviation', 3)
149 .attr('result', 'coloredBlur');
150
151 glow.append('feMerge').selectAll('feMergeNode')
152 .data(['coloredBlur', 'SourceGraphic'])
153 .enter().append('feMergeNode')
154 .attr('in', String);
155 }
156
Simon Hunt95f4b422017-03-03 13:49:05 -0800157 // deprecated -- we'll use something else to highlight instances for affinity
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800158 function loadGlowDefs(defs) {
159 loadGlow(defs, 0.0, 0.0, 0.7, 'blue-glow');
160 loadGlow(defs, 1.0, 1.0, 0.3, 'yellow-glow');
161 }
162
163 // --- Ordinal scales for 7 values.
Simon Huntbb0f2672017-03-28 18:52:59 -0700164 // TODO: migrate these colors to the theme service.
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800165
Simon Huntbb0f2672017-03-28 18:52:59 -0700166 // Colors per Mojo-Design's color palette.. (version one)
Simon Huntdf2a4e62016-08-11 14:21:56 -0700167 // blue red dk grey steel lt blue lt red lt grey
Simon Huntbb0f2672017-03-28 18:52:59 -0700168 // var lightNorm = ['#5b99d2', '#d05a55', '#716b6b', '#7e9aa8', '#66cef6', '#db7773', '#aeada8' ],
169 // lightMute = ['#a8cceb', '#f1a7a7', '#b9b5b5', '#bdcdd5', '#a8e9fd', '#f8c9c9', '#d7d6d4' ],
170
171 // Colors per Mojo-Design's color palette.. (version two)
172 // blue lt blue red green brown teal lime
Steven Burrows1c2a9682017-07-14 16:52:46 +0100173 var lightNorm = ['#5b99d2', '#66cef6', '#d05a55', '#0f9d58', '#ba7941', '#3dc0bf', '#56af00'],
174 lightMute = ['#9ebedf', '#abdef5', '#d79a96', '#7cbe99', '#cdab8d', '#96d5d5', '#a0c96d'],
Simon Huntbb0f2672017-03-28 18:52:59 -0700175
Steven Burrows1c2a9682017-07-14 16:52:46 +0100176 darkNorm = ['#5b99d2', '#66cef6', '#d05a55', '#0f9d58', '#ba7941', '#3dc0bf', '#56af00'],
177 darkMute = ['#9ebedf', '#abdef5', '#d79a96', '#7cbe99', '#cdab8d', '#96d5d5', '#a0c96d'];
Simon Huntbb0f2672017-03-28 18:52:59 -0700178
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800179
180 var colors= {
181 light: {
182 norm: d3.scale.ordinal().range(lightNorm),
Steven Burrows1c2a9682017-07-14 16:52:46 +0100183 mute: d3.scale.ordinal().range(lightMute),
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800184 },
185 dark: {
186 norm: d3.scale.ordinal().range(darkNorm),
Steven Burrows1c2a9682017-07-14 16:52:46 +0100187 mute: d3.scale.ordinal().range(darkMute),
188 },
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800189 };
190
191 function cat7() {
192 var tcid = 'd3utilTestCard';
193
194 function getColor(id, muted, theme) {
195 // NOTE: since we are lazily assigning domain ids, we need to
196 // get the color from all 4 scales, to keep the domains
197 // in sync.
198 var ln = colors.light.norm(id),
199 lm = colors.light.mute(id),
200 dn = colors.dark.norm(id),
201 dm = colors.dark.mute(id);
202 if (theme === 'dark') {
203 return muted ? dm : dn;
204 } else {
205 return muted ? lm : ln;
206 }
207 }
208
209 function testCard(svg) {
210 var g = svg.select('g#' + tcid),
211 dom = d3.range(7),
212 k, muted, theme, what;
213
214 if (!g.empty()) {
215 g.remove();
216
217 } else {
218 g = svg.append('g')
219 .attr('id', tcid)
220 .attr('transform', 'scale(4)translate(20,20)');
221
222 for (k=0; k<4; k++) {
223 muted = k%2;
224 what = muted ? ' muted' : ' normal';
225 theme = k < 2 ? 'light' : 'dark';
226 dom.forEach(function (id, i) {
227 var x = i * 20,
228 y = k * 20,
Simon Hunta9761342016-06-10 18:02:53 -0700229 f = getColor(id, muted, theme);
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800230 g.append('circle').attr({
231 cx: x,
232 cy: y,
233 r: 5,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100234 fill: f,
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800235 });
236 });
237 g.append('rect').attr({
238 x: 140,
239 y: k * 20 - 5,
240 width: 32,
241 height: 10,
242 rx: 2,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100243 fill: '#888',
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800244 });
245 g.append('text').text(theme + what)
246 .attr({
247 x: 142,
248 y: k * 20 + 2,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100249 fill: 'white',
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800250 })
251 .style('font-size', '4pt');
252 }
253 }
254 }
255
256 return {
257 testCard: testCard,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100258 getColor: getColor,
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800259 };
260 }
261
262 function translate(x, y) {
263 if (fs.isA(x) && x.length === 2 && !y) {
264 return 'translate(' + x[0] + ',' + x[1] + ')';
265 }
266 return 'translate(' + x + ',' + y + ')';
267 }
268
269 function scale(x, y) {
270 return 'scale(' + x + ',' + y + ')';
271 }
272
273 function skewX(x) {
274 return 'skewX(' + x + ')';
275 }
276
277 function rotate(deg) {
278 return 'rotate(' + deg + ')';
279 }
280
281 function stripPx(s) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100282 return s.replace(/px$/, '');
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800283 }
284
285 function safeId(s) {
286 return s.replace(/[^a-z0-9]/gi, '-');
287 }
288
289 function makeVisible(el, b) {
290 el.style('visibility', (b ? 'visible' : 'hidden'));
291 }
292
293 function isVisible(el) {
294 return el.style('visibility') === 'visible';
295 }
296
297 function visible(el, x) {
298 if (x === undefined) {
299 return isVisible(el);
300 } else {
301 makeVisible(el, x);
302 }
303 }
304
Simon Hunt737c89f2015-01-28 12:23:19 -0800305 angular.module('onosSvg')
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800306 .factory('SvgUtilService', ['$log', 'FnService',
Simon Hunt737c89f2015-01-28 12:23:19 -0800307 function (_$log_, _fs_) {
308 $log = _$log_;
309 fs = _fs_;
310
Simon Hunt737c89f2015-01-28 12:23:19 -0800311 return {
312 createDragBehavior: createDragBehavior,
Simon Hunt0ee28682015-02-12 20:48:11 -0800313 loadGlowDefs: loadGlowDefs,
Simon Huntc9b73162015-01-29 14:02:15 -0800314 cat7: cat7,
Simon Hunt4b668592015-01-29 17:33:53 -0800315 translate: translate,
Simon Hunt56004a82015-02-19 13:53:20 -0800316 scale: scale,
317 skewX: skewX,
318 rotate: rotate,
Simon Hunt7c8ab8d2015-02-03 15:05:15 -0800319 stripPx: stripPx,
Simon Hunt18bf9822015-02-12 17:35:45 -0800320 safeId: safeId,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100321 visible: visible,
Simon Hunt737c89f2015-01-28 12:23:19 -0800322 };
323 }]);
324}());