blob: 6b4329faffd4ea00a7b5f51e345fbe34e8a2eced [file] [log] [blame]
Simon Hunt25248912014-11-04 11:25:48 -08001/*
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 Hunte7f4bb02014-11-04 15:51:54 -080018 Sample module file to illustrate framework integration.
Simon Hunt25248912014-11-04 11:25:48 -080019
20 @author Simon Hunt
21 */
22
23(function (onos) {
24 'use strict';
25
Simon Hunte7f4bb02014-11-04 15:51:54 -080026 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 Hunt25248912014-11-04 11:25:48 -080042
Simon Hunte7f4bb02014-11-04 15:51:54 -080043 // set the size of the SVG layer to match that of the view
Simon Hunt25248912014-11-04 11:25:48 -080044 function sizeSvg(view) {
45 svg.attr({
46 width: view.width(),
47 height: view.height()
48 });
49 }
50
Simon Hunt25248912014-11-04 11:25:48 -080051 // gets invoked only the first time the view is loaded
52 function preload(view, ctx) {
Simon Hunte7f4bb02014-11-04 15:51:54 -080053 // prepare our SVG layer...
Simon Hunt25248912014-11-04 11:25:48 -080054 svg = view.$div.append('svg');
55 sizeSvg(view);
Simon Hunte7f4bb02014-11-04 15:51:54 -080056 dotG = svg.append('g').attr('id', 'dots');
Simon Hunt25248912014-11-04 11:25:48 -080057 }
58
Simon Hunte7f4bb02014-11-04 15:51:54 -080059 // gets invoked just before our view is loaded
Simon Hunt25248912014-11-04 11:25:48 -080060 function reset(view) {
Simon Hunte7f4bb02014-11-04 15:51:54 -080061 // clear dot group and reset circle data
62 dotG.html('');
63 circleData = [];
64 // also clear text, if any
65 svg.selectAll('text').remove();
Simon Hunt25248912014-11-04 11:25:48 -080066 }
67
Simon Hunte7f4bb02014-11-04 15:51:54 -080068 function updateCirclePositions(view, addNew) {
69 var w = view.width(),
70 h = view.height(),
71 ox = w / 2,
72 oy = h / 2;
Simon Hunt25248912014-11-04 11:25:48 -080073
Simon Hunte7f4bb02014-11-04 15:51:54 -080074 // 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 Hunt25248912014-11-04 11:25:48 -0800126 .attr({
Simon Hunte7f4bb02014-11-04 15:51:54 -0800127 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 Hunt25248912014-11-04 11:25:48 -0800142 })
143 .style({
144 fill: fill,
145 stroke: stroke,
Simon Hunte7f4bb02014-11-04 15:51:54 -0800146 'stroke-width': 3.5,
147 cursor: 'pointer',
148 opacity: 0
Simon Hunt25248912014-11-04 11:25:48 -0800149 })
Simon Hunte7f4bb02014-11-04 15:51:54 -0800150 .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
180 function load(view, ctx) {
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 Hunt25248912014-11-04 11:25:48 -0800198 }
199
200 function resize(view, ctx) {
201 sizeSvg(view);
Simon Hunte7f4bb02014-11-04 15:51:54 -0800202 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 Hunt25248912014-11-04 11:25:48 -0800210 });
211 }
212
Simon Hunte7f4bb02014-11-04 15:51:54 -0800213 // == register our view here, with links to lifecycle callbacks
Simon Hunt25248912014-11-04 11:25:48 -0800214
215 onos.ui.addView('sample', {
216 preload: preload,
217 reset: reset,
218 load: load,
219 resize: resize
220 });
221
Simon Hunt25248912014-11-04 11:25:48 -0800222}(ONOS));