blob: 0a4785f14194fd908d9b9be17f1a6ae31ebbc3a9 [file] [log] [blame]
Simon Hunt2052e5d2015-04-13 17:40:44 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Simon Hunt2052e5d2015-04-13 17:40:44 -07003 *
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 Sprite Module.
Simon Huntabf66d92015-04-15 12:57:31 -070019 Defines behavior for loading sprites into the sprite layer.
Simon Hunt2052e5d2015-04-13 17:40:44 -070020 */
21
22(function () {
23 'use strict';
24
25 // injected refs
Simon Huntabf66d92015-04-15 12:57:31 -070026 var $log, $http, fs, gs, sus, wss;
Simon Huntfd8c7d72015-04-14 17:53:37 -070027
Simon Huntb2c4cc82015-04-15 17:16:28 -070028 // constants
29 var tssid = 'TopoSpriteService: ',
30 fontsize = 20; // default font size 20pt.
Simon Hunt2052e5d2015-04-13 17:40:44 -070031
32 // internal state
Simon Huntabf66d92015-04-15 12:57:31 -070033 var spriteLayer, defsElement;
Simon Hunt2052e5d2015-04-13 17:40:44 -070034
Simon Hunt017a7c32015-04-15 19:23:27 -070035
Simon Huntabf66d92015-04-15 12:57:31 -070036 function registerPathsAsGlyphs(paths) {
37 var custom = {},
38 ids = [];
Simon Hunt2052e5d2015-04-13 17:40:44 -070039
Simon Huntabf66d92015-04-15 12:57:31 -070040 function mkd(d) {
41 return fs.isA(d) ? d.join('') : d;
Simon Hunt2052e5d2015-04-13 17:40:44 -070042 }
43
Simon Hunt017a7c32015-04-15 19:23:27 -070044 paths.forEach(function (path) {
45 var tag = 'spr_' + path.tag;
Simon Hunt2052e5d2015-04-13 17:40:44 -070046
Simon Hunt017a7c32015-04-15 19:23:27 -070047 if (path.glyph) {
48 // assumption is that we are using a built-in glyph
49 return;
50 }
51
52 custom['_' + tag] = path.viewbox || '0 0 1000 1000';
53 custom[tag] = mkd(path.d);
54 ids.push(tag);
55 });
56
57 gs.registerGlyphs(custom);
58 gs.loadDefs(defsElement, ids, true);
Simon Huntabf66d92015-04-15 12:57:31 -070059 }
60
Simon Hunt7f62f7c2015-05-11 17:38:02 -070061 function applyStrokeStyle(s, use) {
62 var style;
63 if (s) {
64 style = {};
65 angular.forEach(s, function (value, key) {
66 style['stroke-' + key] = value;
67 });
68 use.style(style);
69 }
70 }
Simon Huntabf66d92015-04-15 12:57:31 -070071
Simon Hunt7f62f7c2015-05-11 17:38:02 -070072 function applyFillClass(f, use) {
73 use.classed('fill-' + f, true);
74 }
75
76 function doSprite(spr, def, pathmeta) {
77 var pmeta = pathmeta[def.path],
78 c = spr.class || 'gray1',
Simon Huntabf66d92015-04-15 12:57:31 -070079 p = spr.pos || [0,0],
80 lab = spr.label,
Simon Huntb2c4cc82015-04-15 17:16:28 -070081 dim = def.dim || [40,40],
Simon Huntabf66d92015-04-15 12:57:31 -070082 w = dim[0],
83 h = dim[1],
Simon Huntb2c4cc82015-04-15 17:16:28 -070084 dy = def.labelyoff || 1,
85 sc = def.scale,
86 xfm = sus.translate(p),
Simon Hunt7f62f7c2015-05-11 17:38:02 -070087 g, attr, use;
Simon Hunt2052e5d2015-04-13 17:40:44 -070088
Simon Huntb2c4cc82015-04-15 17:16:28 -070089 if (sc) {
90 xfm += sus.scale(sc, sc);
91 }
92
93 g = spriteLayer.append('g')
94 .classed(c, true)
95 .attr('transform', xfm);
96
97 attr = {
Simon Huntabf66d92015-04-15 12:57:31 -070098 width: w,
99 height: h,
Simon Hunt017a7c32015-04-15 19:23:27 -0700100 'xlink:href': '#' + pmeta.u
Simon Huntb2c4cc82015-04-15 17:16:28 -0700101 };
102
103 use = g.append('use').attr(attr);
Simon Hunt7f62f7c2015-05-11 17:38:02 -0700104 applyStrokeStyle(pmeta.s, use);
105 applyFillClass(def.fill, use);
Simon Huntb2c4cc82015-04-15 17:16:28 -0700106
Simon Hunt7f62f7c2015-05-11 17:38:02 -0700107
108 // add subpaths if they have been defined
109 if (fs.isA(def.subpaths)) {
110 def.subpaths.forEach(function (v) {
111 pmeta = pathmeta[v.path];
112 attr = {
113 width: w,
114 height: h,
115 'xlink:href': '#' + pmeta.u,
116 transform: sus.translate(v.pos)
117 };
118 use = g.append('use').attr(attr);
119 applyStrokeStyle(pmeta.s, use);
120 applyFillClass(def.subpathfill, use);
Simon Huntb2c4cc82015-04-15 17:16:28 -0700121 });
Simon Huntb2c4cc82015-04-15 17:16:28 -0700122 }
Simon Huntabf66d92015-04-15 12:57:31 -0700123
124 if (lab) {
125 g.append('text')
126 .text(lab)
Simon Huntb2c4cc82015-04-15 17:16:28 -0700127 .attr({ x: w / 2, y: h * dy });
Simon Huntabf66d92015-04-15 12:57:31 -0700128 }
Simon Hunt2052e5d2015-04-13 17:40:44 -0700129 }
130
Simon Huntabf66d92015-04-15 12:57:31 -0700131 function doLabel(label) {
132 var c = label.class || 'gray1',
Simon Huntb2c4cc82015-04-15 17:16:28 -0700133 p = label.pos || [0,0],
134 sz = label.size || 1.0,
135 g = spriteLayer.append('g')
136 .classed(c, true)
137 .attr('transform', sus.translate(p))
138 .append('text')
139 .text(label.text)
140 .style('font-size', (fontsize * sz)+'pt');
Simon Huntabf66d92015-04-15 12:57:31 -0700141 }
142
143
Simon Huntfd8c7d72015-04-14 17:53:37 -0700144 // ==========================
145 // event handlers
Simon Hunt2052e5d2015-04-13 17:40:44 -0700146
Simon Huntfd8c7d72015-04-14 17:53:37 -0700147 // Handles response from 'spriteListRequest' which lists all the
148 // registered sprite definitions on the server.
149 // (see onos-upload-sprites)
150 function inList(payload) {
151 $log.debug(tssid + 'Registered sprite definitions:', payload.names);
152 // Some day, we will make this list available to the user in
153 // a dropdown selection box...
Simon Hunt2052e5d2015-04-13 17:40:44 -0700154 }
155
Simon Huntfd8c7d72015-04-14 17:53:37 -0700156 // Handles response from 'spriteDataRequest' which provides the
157 // data for the requested sprite definition.
158 function inData(payload) {
159 var data = payload.data,
Simon Hunt017a7c32015-04-15 19:23:27 -0700160 name, desc, pfx, sprites, labels, alpha,
161 paths, defn, load,
162 pathmeta = {},
163 defs = {},
164 warn = [];
Simon Huntfd8c7d72015-04-14 17:53:37 -0700165
166 if (!data) {
Simon Hunt017a7c32015-04-15 19:23:27 -0700167 $log.warn(tssid + 'No sprite data loaded.');
Simon Huntfd8c7d72015-04-14 17:53:37 -0700168 return;
169 }
Simon Huntabf66d92015-04-15 12:57:31 -0700170 name = data.defn_name;
171 desc = data.defn_desc;
Simon Hunt017a7c32015-04-15 19:23:27 -0700172 paths = data.paths;
173 defn = data.defn;
174 load = data.load;
175 pfx = tssid + '[' + name + ']: ';
Simon Huntfd8c7d72015-04-14 17:53:37 -0700176
177 $log.debug("Loading sprites...[" + name + "]", desc);
178
Simon Hunt017a7c32015-04-15 19:23:27 -0700179 function no(what) {
180 warn.push(pfx + 'No ' + what + ' property defined');
Simon Huntb2c4cc82015-04-15 17:16:28 -0700181 }
Simon Huntfd8c7d72015-04-14 17:53:37 -0700182
Simon Hunt017a7c32015-04-15 19:23:27 -0700183 if (!paths) no('paths');
184 if (!defn) no('defn');
185 if (!load) no('load');
186
187 if (warn.length) {
188 $log.error(warn.join('\n'));
189 return;
Simon Huntabf66d92015-04-15 12:57:31 -0700190 }
191
Simon Hunt017a7c32015-04-15 19:23:27 -0700192 // any custom paths need to be added to the glyph DB, and imported
193 registerPathsAsGlyphs(paths);
194
195 paths.forEach(function (p) {
196 pathmeta[p.tag] = {
197 s: p.stroke,
198 u: p.glyph || 'spr_' + p.tag
199 };
200 });
201
202 defn.forEach(function (d) {
203 defs[d.id] = d;
204 });
205
206 // sprites, labels and alpha are each optional components of the load
207 sprites = load.sprites;
208 labels = load.labels;
209 alpha = load.alpha;
210
211 if (alpha) {
212 spriteLayer.style('opacity', alpha);
Simon Huntabf66d92015-04-15 12:57:31 -0700213 }
214
215 if (sprites) {
216 sprites.forEach(function (spr) {
Simon Hunt7f62f7c2015-05-11 17:38:02 -0700217 var def = defs[spr.id];
218 doSprite(spr, def, pathmeta);
Simon Huntabf66d92015-04-15 12:57:31 -0700219 });
220 }
221
222 if (labels) {
223 labels.forEach(doLabel);
224 }
Simon Huntfd8c7d72015-04-14 17:53:37 -0700225 }
226
227
Simon Huntabf66d92015-04-15 12:57:31 -0700228 function loadSprites(layer, defsElem, defname) {
Simon Huntfd8c7d72015-04-14 17:53:37 -0700229 var name = defname || 'sprites';
230 spriteLayer = layer;
Simon Huntabf66d92015-04-15 12:57:31 -0700231 defsElement = defsElem;
Simon Huntfd8c7d72015-04-14 17:53:37 -0700232
233 $log.info(tssid + 'Requesting sprite definition ['+name+']...');
234
235 wss.sendEvent('spriteListRequest');
236 wss.sendEvent('spriteDataRequest', {name: name});
237 }
Simon Hunt2052e5d2015-04-13 17:40:44 -0700238
239 // === -----------------------------------------------------
240 // === MODULE DEFINITION ===
241
242 angular.module('ovTopo')
243 .factory('TopoSpriteService',
Simon Huntabf66d92015-04-15 12:57:31 -0700244 ['$log', '$http', 'FnService', 'GlyphService',
245 'SvgUtilService', 'WebSocketService',
Simon Hunt2052e5d2015-04-13 17:40:44 -0700246
Simon Huntabf66d92015-04-15 12:57:31 -0700247 function (_$log_, _$http_, _fs_, _gs_, _sus_, _wss_) {
Simon Hunt2052e5d2015-04-13 17:40:44 -0700248 $log = _$log_;
249 $http = _$http_;
250 fs = _fs_;
Simon Huntabf66d92015-04-15 12:57:31 -0700251 gs = _gs_;
Simon Hunt2052e5d2015-04-13 17:40:44 -0700252 sus = _sus_;
Simon Huntfd8c7d72015-04-14 17:53:37 -0700253 wss = _wss_;
Simon Hunt2052e5d2015-04-13 17:40:44 -0700254
255 return {
Simon Huntfd8c7d72015-04-14 17:53:37 -0700256 loadSprites: loadSprites,
257 spriteListResponse: inList,
258 spriteDataResponse: inData
Simon Hunt2052e5d2015-04-13 17:40:44 -0700259 };
260 }]);
261
262}());