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