aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/web/gui/src/main/webapp/app/fw/svg/svgUtil.js')
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/svg/svgUtil.js311
1 files changed, 311 insertions, 0 deletions
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/svgUtil.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
new file mode 100644
index 00000000..cb67ae83
--- /dev/null
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- SVG -- Util Service
+ */
+
+/*
+ The SVG Util Service provides a miscellany of utility functions.
+ */
+
+(function () {
+ 'use strict';
+
+ // injected references
+ var $log, fs;
+
+ angular.module('onosSvg')
+ .factory('SvgUtilService', ['$log', 'FnService',
+ function (_$log_, _fs_) {
+ $log = _$log_;
+ fs = _fs_;
+
+ // TODO: change 'force' ref to be 'force.alpha' ref.
+ function createDragBehavior(force, selectCb, atDragEnd,
+ dragEnabled, clickEnabled) {
+ var draggedThreshold = d3.scale.linear()
+ .domain([0, 0.1])
+ .range([5, 20])
+ .clamp(true),
+ drag,
+ fSel = fs.isF(selectCb),
+ fEnd = fs.isF(atDragEnd),
+ fDEn = fs.isF(dragEnabled),
+ fCEn = fs.isF(clickEnabled),
+ bad = [];
+
+ function naf(what) {
+ return 'SvgUtilService: createDragBehavior(): ' + what +
+ ' is not a function';
+ }
+
+ if (!force) {
+ bad.push('SvgUtilService: createDragBehavior(): ' +
+ 'Bad force reference');
+ }
+ if (!fSel) {
+ bad.push(naf('selectCb'));
+ }
+ if (!fEnd) {
+ bad.push(naf('atDragEnd'));
+ }
+ if (!fDEn) {
+ bad.push(naf('dragEnabled'));
+ }
+ if (!fCEn) {
+ bad.push(naf('clickEnabled'));
+ }
+
+ if (bad.length) {
+ $log.error(bad.join('\n'));
+ return null;
+ }
+
+ function dragged(d) {
+ var threshold = draggedThreshold(force.alpha()),
+ dx = d.oldX - d.px,
+ dy = d.oldY - d.py;
+ if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
+ d.dragged = true;
+ }
+ return d.dragged;
+ }
+
+ drag = d3.behavior.drag()
+ .origin(function(d) { return d; })
+ .on('dragstart', function(d) {
+ if (clickEnabled() || dragEnabled()) {
+ d3.event.sourceEvent.stopPropagation();
+
+ d.oldX = d.x;
+ d.oldY = d.y;
+ d.dragged = false;
+ d.fixed |= 2;
+ d.dragStarted = true;
+ }
+ })
+ .on('drag', function(d) {
+ if (dragEnabled()) {
+ d.px = d3.event.x;
+ d.py = d3.event.y;
+ if (dragged(d)) {
+ if (!force.alpha()) {
+ force.alpha(.025);
+ }
+ }
+ }
+ })
+ .on('dragend', function(d) {
+ if (d.dragStarted) {
+ d.dragStarted = false;
+ if (!dragged(d)) {
+ // consider this the same as a 'click'
+ // (selection of a node)
+ if (clickEnabled()) {
+ selectCb.call(this, d);
+ }
+ }
+ d.fixed &= ~6;
+
+ // hook at the end of a drag gesture
+ if (dragEnabled()) {
+ atDragEnd.call(this, d);
+ }
+ }
+ });
+
+ return drag;
+ }
+
+
+ function loadGlow(defs, r, g, b, id) {
+ var glow = defs.append('filter')
+ .attr('x', '-50%')
+ .attr('y', '-50%')
+ .attr('width', '200%')
+ .attr('height', '200%')
+ .attr('id', id);
+
+ glow.append('feColorMatrix')
+ .attr('type', 'matrix')
+ .attr('values',
+ '0 0 0 0 ' + r + ' ' +
+ '0 0 0 0 ' + g + ' ' +
+ '0 0 0 0 ' + b + ' ' +
+ '0 0 0 1 0 ');
+
+ glow.append('feGaussianBlur')
+ .attr('stdDeviation', 3)
+ .attr('result', 'coloredBlur');
+
+ glow.append('feMerge').selectAll('feMergeNode')
+ .data(['coloredBlur', 'SourceGraphic'])
+ .enter().append('feMergeNode')
+ .attr('in', String);
+ }
+
+ function loadGlowDefs(defs) {
+ loadGlow(defs, 0.0, 0.0, 0.7, 'blue-glow');
+ loadGlow(defs, 1.0, 1.0, 0.3, 'yellow-glow');
+ }
+
+ // --- Ordinal scales for 7 values.
+
+ // blue brown brick red sea green purple dark teal lime
+ var lightNorm = ['#3E5780', '#78533B', '#CB4D28', '#018D61', '#8A2979', '#006D73', '#56AF00'],
+ lightMute = ['#A8B8CC', '#CCB3A8', '#FFC2BD', '#96D6BF', '#D19FCE', '#8FCCCA', '#CAEAA4'],
+
+ darkNorm = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'],
+ darkMute = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'];
+
+ var colors= {
+ light: {
+ norm: d3.scale.ordinal().range(lightNorm),
+ mute: d3.scale.ordinal().range(lightMute)
+ },
+ dark: {
+ norm: d3.scale.ordinal().range(darkNorm),
+ mute: d3.scale.ordinal().range(darkMute)
+ }
+ };
+
+ function cat7() {
+ var tcid = 'd3utilTestCard';
+
+ function getColor(id, muted, theme) {
+ // NOTE: since we are lazily assigning domain ids, we need to
+ // get the color from all 4 scales, to keep the domains
+ // in sync.
+ var ln = colors.light.norm(id),
+ lm = colors.light.mute(id),
+ dn = colors.dark.norm(id),
+ dm = colors.dark.mute(id);
+ if (theme === 'dark') {
+ return muted ? dm : dn;
+ } else {
+ return muted ? lm : ln;
+ }
+ }
+
+ function testCard(svg) {
+ var g = svg.select('g#' + tcid),
+ dom = d3.range(7),
+ k, muted, theme, what;
+
+ if (!g.empty()) {
+ g.remove();
+
+ } else {
+ g = svg.append('g')
+ .attr('id', tcid)
+ .attr('transform', 'scale(4)translate(20,20)');
+
+ for (k=0; k<4; k++) {
+ muted = k%2;
+ what = muted ? ' muted' : ' normal';
+ theme = k < 2 ? 'light' : 'dark';
+ dom.forEach(function (id, i) {
+ var x = i * 20,
+ y = k * 20,
+ f = get(id, muted, theme);
+ g.append('circle').attr({
+ cx: x,
+ cy: y,
+ r: 5,
+ fill: f
+ });
+ });
+ g.append('rect').attr({
+ x: 140,
+ y: k * 20 - 5,
+ width: 32,
+ height: 10,
+ rx: 2,
+ fill: '#888'
+ });
+ g.append('text').text(theme + what)
+ .attr({
+ x: 142,
+ y: k * 20 + 2,
+ fill: 'white'
+ })
+ .style('font-size', '4pt');
+ }
+ }
+ }
+
+ return {
+ testCard: testCard,
+ getColor: getColor
+ };
+ }
+
+ function translate(x, y) {
+ if (fs.isA(x) && x.length === 2 && !y) {
+ return 'translate(' + x[0] + ',' + x[1] + ')';
+ }
+ return 'translate(' + x + ',' + y + ')';
+ }
+
+ function scale(x, y) {
+ return 'scale(' + x + ',' + y + ')';
+ }
+
+ function skewX(x) {
+ return 'skewX(' + x + ')';
+ }
+
+ function rotate(deg) {
+ return 'rotate(' + deg + ')';
+ }
+
+ function stripPx(s) {
+ return s.replace(/px$/,'');
+ }
+
+ function safeId(s) {
+ return s.replace(/[^a-z0-9]/gi, '-');
+ }
+
+ function makeVisible(el, b) {
+ el.style('visibility', (b ? 'visible' : 'hidden'));
+ }
+
+ function isVisible(el) {
+ return el.style('visibility') === 'visible';
+ }
+
+ return {
+ createDragBehavior: createDragBehavior,
+ loadGlowDefs: loadGlowDefs,
+ cat7: cat7,
+ translate: translate,
+ scale: scale,
+ skewX: skewX,
+ rotate: rotate,
+ stripPx: stripPx,
+ safeId: safeId,
+ visible: function (el, x) {
+ if (x === undefined) {
+ return isVisible(el);
+ } else {
+ makeVisible(el, x);
+ }
+ }
+ };
+ }]);
+}());