blob: 0f375e26f92fd160fd18d237e72bd3f705eb6cfa [file] [log] [blame]
Simon Hunt737c89f2015-01-28 12:23:19 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
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,
33 dragEnabled, clickEnabled) {
34 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) {
73 var threshold = draggedThreshold(force.alpha()),
74 dx = d.oldX - d.px,
75 dy = d.oldY - d.py;
76 if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
77 d.dragged = true;
78 }
79 return d.dragged;
80 }
81
82 drag = d3.behavior.drag()
83 .origin(function(d) { return d; })
84 .on('dragstart', function(d) {
85 if (clickEnabled() || dragEnabled()) {
86 d3.event.sourceEvent.stopPropagation();
87
88 d.oldX = d.x;
89 d.oldY = d.y;
90 d.dragged = false;
91 d.fixed |= 2;
92 d.dragStarted = true;
93 }
94 })
95 .on('drag', function(d) {
96 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 })
106 .on('dragend', function(d) {
107 if (d.dragStarted) {
108 d.dragStarted = false;
109 if (!dragged(d)) {
110 // consider this the same as a 'click'
111 // (selection of a node)
112 if (clickEnabled()) {
113 selectCb.call(this, d);
114 }
115 }
116 d.fixed &= ~6;
117
118 // hook at the end of a drag gesture
119 if (dragEnabled()) {
120 atDragEnd.call(this, d);
121 }
122 }
123 });
124
125 return drag;
126 }
127
128
129 function loadGlow(defs, r, g, b, id) {
130 var glow = defs.append('filter')
131 .attr('x', '-50%')
132 .attr('y', '-50%')
133 .attr('width', '200%')
134 .attr('height', '200%')
135 .attr('id', id);
136
137 glow.append('feColorMatrix')
138 .attr('type', 'matrix')
139 .attr('values',
140 '0 0 0 0 ' + r + ' ' +
141 '0 0 0 0 ' + g + ' ' +
142 '0 0 0 0 ' + b + ' ' +
143 '0 0 0 1 0 ');
144
145 glow.append('feGaussianBlur')
146 .attr('stdDeviation', 3)
147 .attr('result', 'coloredBlur');
148
149 glow.append('feMerge').selectAll('feMergeNode')
150 .data(['coloredBlur', 'SourceGraphic'])
151 .enter().append('feMergeNode')
152 .attr('in', String);
153 }
154
155 function loadGlowDefs(defs) {
156 loadGlow(defs, 0.0, 0.0, 0.7, 'blue-glow');
157 loadGlow(defs, 1.0, 1.0, 0.3, 'yellow-glow');
158 }
159
160 // --- Ordinal scales for 7 values.
161
Simon Hunta9761342016-06-10 18:02:53 -0700162 // Colors per Mojo-Design's color palette..
Simon Huntdf2a4e62016-08-11 14:21:56 -0700163 // blue red dk grey steel lt blue lt red lt grey
164 var lightNorm = ['#5b99d2', '#d05a55', '#716b6b', '#7e9aa8', '#66cef6', '#db7773', '#aeada8' ],
165 lightMute = ['#a8cceb', '#f1a7a7', '#b9b5b5', '#bdcdd5', '#a8e9fd', '#f8c9c9', '#d7d6d4' ],
Simon Hunta9761342016-06-10 18:02:53 -0700166 // TODO: dark theme
Simon Huntdf2a4e62016-08-11 14:21:56 -0700167 darkNorm = ['#5b99d2', '#d05a55', '#716b6b', '#7e9aa8', '#66cef6', '#db7773', '#aeada8' ],
168 darkMute = ['#a8cceb', '#f1a7a7', '#b9b5b5', '#bdcdd5', '#a8e9fd', '#f8c9c9', '#d7d6d4' ];
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800169
170 var colors= {
171 light: {
172 norm: d3.scale.ordinal().range(lightNorm),
173 mute: d3.scale.ordinal().range(lightMute)
174 },
175 dark: {
176 norm: d3.scale.ordinal().range(darkNorm),
177 mute: d3.scale.ordinal().range(darkMute)
178 }
179 };
180
181 function cat7() {
182 var tcid = 'd3utilTestCard';
183
184 function getColor(id, muted, theme) {
185 // NOTE: since we are lazily assigning domain ids, we need to
186 // get the color from all 4 scales, to keep the domains
187 // in sync.
188 var ln = colors.light.norm(id),
189 lm = colors.light.mute(id),
190 dn = colors.dark.norm(id),
191 dm = colors.dark.mute(id);
192 if (theme === 'dark') {
193 return muted ? dm : dn;
194 } else {
195 return muted ? lm : ln;
196 }
197 }
198
199 function testCard(svg) {
200 var g = svg.select('g#' + tcid),
201 dom = d3.range(7),
202 k, muted, theme, what;
203
204 if (!g.empty()) {
205 g.remove();
206
207 } else {
208 g = svg.append('g')
209 .attr('id', tcid)
210 .attr('transform', 'scale(4)translate(20,20)');
211
212 for (k=0; k<4; k++) {
213 muted = k%2;
214 what = muted ? ' muted' : ' normal';
215 theme = k < 2 ? 'light' : 'dark';
216 dom.forEach(function (id, i) {
217 var x = i * 20,
218 y = k * 20,
Simon Hunta9761342016-06-10 18:02:53 -0700219 f = getColor(id, muted, theme);
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800220 g.append('circle').attr({
221 cx: x,
222 cy: y,
223 r: 5,
224 fill: f
225 });
226 });
227 g.append('rect').attr({
228 x: 140,
229 y: k * 20 - 5,
230 width: 32,
231 height: 10,
232 rx: 2,
233 fill: '#888'
234 });
235 g.append('text').text(theme + what)
236 .attr({
237 x: 142,
238 y: k * 20 + 2,
239 fill: 'white'
240 })
241 .style('font-size', '4pt');
242 }
243 }
244 }
245
246 return {
247 testCard: testCard,
248 getColor: getColor
249 };
250 }
251
252 function translate(x, y) {
253 if (fs.isA(x) && x.length === 2 && !y) {
254 return 'translate(' + x[0] + ',' + x[1] + ')';
255 }
256 return 'translate(' + x + ',' + y + ')';
257 }
258
259 function scale(x, y) {
260 return 'scale(' + x + ',' + y + ')';
261 }
262
263 function skewX(x) {
264 return 'skewX(' + x + ')';
265 }
266
267 function rotate(deg) {
268 return 'rotate(' + deg + ')';
269 }
270
271 function stripPx(s) {
272 return s.replace(/px$/,'');
273 }
274
275 function safeId(s) {
276 return s.replace(/[^a-z0-9]/gi, '-');
277 }
278
279 function makeVisible(el, b) {
280 el.style('visibility', (b ? 'visible' : 'hidden'));
281 }
282
283 function isVisible(el) {
284 return el.style('visibility') === 'visible';
285 }
286
287 function visible(el, x) {
288 if (x === undefined) {
289 return isVisible(el);
290 } else {
291 makeVisible(el, x);
292 }
293 }
294
Simon Hunt737c89f2015-01-28 12:23:19 -0800295 angular.module('onosSvg')
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800296 .factory('SvgUtilService', ['$log', 'FnService',
Simon Hunt737c89f2015-01-28 12:23:19 -0800297 function (_$log_, _fs_) {
298 $log = _$log_;
299 fs = _fs_;
300
Simon Hunt737c89f2015-01-28 12:23:19 -0800301 return {
302 createDragBehavior: createDragBehavior,
Simon Hunt0ee28682015-02-12 20:48:11 -0800303 loadGlowDefs: loadGlowDefs,
Simon Huntc9b73162015-01-29 14:02:15 -0800304 cat7: cat7,
Simon Hunt4b668592015-01-29 17:33:53 -0800305 translate: translate,
Simon Hunt56004a82015-02-19 13:53:20 -0800306 scale: scale,
307 skewX: skewX,
308 rotate: rotate,
Simon Hunt7c8ab8d2015-02-03 15:05:15 -0800309 stripPx: stripPx,
Simon Hunt18bf9822015-02-12 17:35:45 -0800310 safeId: safeId,
Simon Huntf4ef6dd2016-02-03 17:05:14 -0800311 visible: visible
Simon Hunt737c89f2015-01-28 12:23:19 -0800312 };
313 }]);
314}());