Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014 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 | /* |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 18 | Sample module file to illustrate framework integration. |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 19 | */ |
| 20 | |
| 21 | (function (onos) { |
| 22 | 'use strict'; |
| 23 | |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 24 | var pi = Math.PI, |
| 25 | svg, |
| 26 | dotG, |
| 27 | nCircles = 12, |
| 28 | circleData = [], |
| 29 | dotId = 0, |
| 30 | angle = 360 / nCircles, |
| 31 | baseAngle = -90 - angle, |
| 32 | groupRadius = 120, |
| 33 | dotRadius = 24, |
| 34 | dotMoveMs = 800, |
| 35 | dotAppearMs = 300, |
| 36 | dotEase = 'elastic', |
| 37 | colorScale = d3.scale.linear() |
| 38 | .domain([-pi/2, 2*pi/4, 3*pi/2]) |
| 39 | .range(['green', 'goldenrod', 'blue']); |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 40 | |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 41 | // set the size of the SVG layer to match that of the view |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 42 | function sizeSvg(view) { |
| 43 | svg.attr({ |
| 44 | width: view.width(), |
| 45 | height: view.height() |
| 46 | }); |
| 47 | } |
| 48 | |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 49 | // gets invoked only the first time the view is loaded |
Simon Hunt | a2994cc | 2014-12-02 14:19:15 -0800 | [diff] [blame] | 50 | function init(view, ctx, flags) { |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 51 | // prepare our SVG layer... |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 52 | svg = view.$div.append('svg'); |
| 53 | sizeSvg(view); |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 54 | dotG = svg.append('g').attr('id', 'dots'); |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 55 | } |
| 56 | |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 57 | // gets invoked just before our view is loaded |
Simon Hunt | a2994cc | 2014-12-02 14:19:15 -0800 | [diff] [blame] | 58 | function reset(view, ctx, flags) { |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 59 | // clear dot group and reset circle data |
| 60 | dotG.html(''); |
| 61 | circleData = []; |
| 62 | // also clear text, if any |
| 63 | svg.selectAll('text').remove(); |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 64 | } |
| 65 | |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 66 | function updateCirclePositions(view, addNew) { |
| 67 | var w = view.width(), |
| 68 | h = view.height(), |
| 69 | ox = w / 2, |
| 70 | oy = h / 2; |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 71 | |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 72 | // reposition existing dots |
| 73 | circleData.forEach(function (c, i) { |
| 74 | var inc = addNew ? 1 : 0, |
| 75 | theta = ((i + inc) * angle + baseAngle) * pi/180, |
| 76 | dx = Math.cos(theta) * groupRadius, |
| 77 | dy = Math.sin(theta) * groupRadius, |
| 78 | x = ox + dx, |
| 79 | y = oy + dy; |
| 80 | if (!addNew && i === 0) { |
| 81 | x = ox; |
| 82 | y = oy; |
| 83 | } |
| 84 | c.cx = x; |
| 85 | c.cy = y; |
| 86 | c.rgb = colorScale(theta); |
| 87 | }); |
| 88 | |
| 89 | if (addNew) { |
| 90 | // introduce a new dot |
| 91 | circleData.unshift({ |
| 92 | cx: ox, |
| 93 | cy: oy, |
| 94 | id: dotId++ |
| 95 | }); |
| 96 | } |
| 97 | |
| 98 | // +1 to account for the circle in the center.. |
| 99 | if (circleData.length > nCircles + 1) { |
| 100 | circleData.splice(nCircles + 1, 1); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | function doCircles(view) { |
| 105 | var ox = view.width() / 2, |
| 106 | oy = view.height() / 2, |
| 107 | stroke = 'black', |
| 108 | fill = 'red', |
| 109 | hoverFill = 'magenta'; |
| 110 | |
| 111 | // move existing circles, and add a new one |
| 112 | updateCirclePositions(view, true); |
| 113 | |
| 114 | var circ = dotG.selectAll('circle') |
| 115 | .data(circleData, function (d) { return d.id; }); |
| 116 | |
| 117 | // operate on existing elements |
| 118 | circ.on('mouseover', null) |
| 119 | .on('mouseout', null) |
| 120 | .on('click', null) |
| 121 | .transition() |
| 122 | .duration(dotMoveMs) |
| 123 | .ease(dotEase) |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 124 | .attr({ |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 125 | cx: function (d) { return d.cx; }, |
| 126 | cy: function (d) { return d.cy; } |
| 127 | }) |
| 128 | .style({ |
| 129 | cursor: 'default', |
| 130 | fill: function (d) { return d.rgb; } |
| 131 | }); |
| 132 | |
| 133 | // operate on entering elements |
| 134 | circ.enter() |
| 135 | .append('circle') |
| 136 | .attr({ |
| 137 | cx: function (d) { return d.cx; }, |
| 138 | cy: function (d) { return d.cy; }, |
| 139 | r: 0 |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 140 | }) |
| 141 | .style({ |
| 142 | fill: fill, |
| 143 | stroke: stroke, |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 144 | 'stroke-width': 3.5, |
| 145 | cursor: 'pointer', |
| 146 | opacity: 0 |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 147 | }) |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 148 | .on('mouseover', function (d) { |
| 149 | d3.select(this).style('fill', hoverFill); |
| 150 | }) |
| 151 | .on('mouseout', function (d) { |
| 152 | d3.select(this).style('fill', fill); |
| 153 | }) |
| 154 | .on('click', function (d) { |
| 155 | setTimeout(function() { |
| 156 | doCircles(view, true); |
| 157 | }, 10); |
| 158 | }) |
| 159 | .transition() |
| 160 | .delay(dotMoveMs) |
| 161 | .duration(dotAppearMs) |
| 162 | .attr('r', dotRadius) |
| 163 | .style('opacity', 1); |
| 164 | |
| 165 | // operate on exiting elements |
| 166 | circ.exit() |
| 167 | .transition() |
| 168 | .duration(750) |
| 169 | .style('opacity', 0) |
| 170 | .attr({ |
| 171 | cx: ox, |
| 172 | cy: oy, |
| 173 | r: groupRadius - dotRadius |
| 174 | }) |
| 175 | .remove(); |
| 176 | } |
| 177 | |
Simon Hunt | a2994cc | 2014-12-02 14:19:15 -0800 | [diff] [blame] | 178 | function load(view, ctx, flags) { |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 179 | var ctxText = ctx ? 'Context is "' + ctx + '"' : ''; |
| 180 | |
| 181 | // display our view context |
| 182 | if (ctxText) { |
| 183 | svg.append('text') |
| 184 | .text(ctxText) |
| 185 | .attr({ |
| 186 | x: 20, |
| 187 | y: '1.5em' |
| 188 | }) |
| 189 | .style({ |
| 190 | fill: 'darkgreen', |
| 191 | 'font-size': '20pt' |
| 192 | }); |
| 193 | } |
| 194 | |
| 195 | doCircles(view); |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 196 | } |
| 197 | |
Simon Hunt | a2994cc | 2014-12-02 14:19:15 -0800 | [diff] [blame] | 198 | function resize(view, ctx, flags) { |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 199 | sizeSvg(view); |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 200 | updateCirclePositions(view); |
| 201 | |
| 202 | // move exiting dots into new positions, relative to view size |
| 203 | var circ = dotG.selectAll('circle') |
| 204 | .data(circleData, function (d) { return d.id; }); |
| 205 | circ.attr({ |
| 206 | cx: function (d) { return d.cx; }, |
| 207 | cy: function (d) { return d.cy; } |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 208 | }); |
| 209 | } |
| 210 | |
Simon Hunt | e7f4bb0 | 2014-11-04 15:51:54 -0800 | [diff] [blame] | 211 | // == register our view here, with links to lifecycle callbacks |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 212 | |
| 213 | onos.ui.addView('sample', { |
Simon Hunt | a2994cc | 2014-12-02 14:19:15 -0800 | [diff] [blame] | 214 | init: init, |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 215 | reset: reset, |
| 216 | load: load, |
| 217 | resize: resize |
| 218 | }); |
| 219 | |
Simon Hunt | 2524891 | 2014-11-04 11:25:48 -0800 | [diff] [blame] | 220 | }(ONOS)); |