babushka-viz 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,314 @@
1
+ /**
2
+ Copyright (c) 2010 Dennis Hotson
3
+
4
+ Permission is hereby granted, free of charge, to any person
5
+ obtaining a copy of this software and associated documentation
6
+ files (the "Software"), to deal in the Software without
7
+ restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+ (function() {
27
+
28
+ jQuery.fn.springy = function(params) {
29
+ var graph = this.graph = params.graph || new Springy.Graph();
30
+
31
+ var stiffness = params.stiffness || 400.0;
32
+ var repulsion = params.repulsion || 400.0;
33
+ var damping = params.damping || 0.5;
34
+ var nodeSelected = params.nodeSelected || null;
35
+
36
+ var canvas = this[0];
37
+ var ctx = canvas.getContext("2d");
38
+
39
+ var layout = this.layout = new Springy.Layout.ForceDirected(graph, stiffness, repulsion, damping);
40
+
41
+ // calculate bounding box of graph layout.. with ease-in
42
+ var currentBB = layout.getBoundingBox();
43
+ var targetBB = {bottomleft: new Springy.Vector(-2, -2), topright: new Springy.Vector(2, 2)};
44
+
45
+ // auto adjusting bounding box
46
+ Springy.requestAnimationFrame(function adjust() {
47
+ targetBB = layout.getBoundingBox();
48
+ // current gets 20% closer to target every iteration
49
+ currentBB = {
50
+ bottomleft: currentBB.bottomleft.add( targetBB.bottomleft.subtract(currentBB.bottomleft)
51
+ .divide(10)),
52
+ topright: currentBB.topright.add( targetBB.topright.subtract(currentBB.topright)
53
+ .divide(10))
54
+ };
55
+
56
+ Springy.requestAnimationFrame(adjust);
57
+ });
58
+
59
+ // convert to/from screen coordinates
60
+ var toScreen = function(p) {
61
+ var size = currentBB.topright.subtract(currentBB.bottomleft);
62
+ var sx = p.subtract(currentBB.bottomleft).divide(size.x).x * canvas.width;
63
+ var sy = p.subtract(currentBB.bottomleft).divide(size.y).y * canvas.height;
64
+ return new Springy.Vector(sx, sy);
65
+ };
66
+
67
+ var fromScreen = function(s) {
68
+ var size = currentBB.topright.subtract(currentBB.bottomleft);
69
+ var px = (s.x / canvas.width) * size.x + currentBB.bottomleft.x;
70
+ var py = (s.y / canvas.height) * size.y + currentBB.bottomleft.y;
71
+ return new Springy.Vector(px, py);
72
+ };
73
+
74
+ // half-assed drag and drop
75
+ var selected = null;
76
+ var nearest = null;
77
+ var dragged = null;
78
+
79
+ jQuery(canvas).mousedown(function(e) {
80
+ var pos = jQuery(this).offset();
81
+ var p = fromScreen({x: e.pageX - pos.left, y: e.pageY - pos.top});
82
+ selected = nearest = dragged = layout.nearest(p);
83
+
84
+ if (selected.node !== null) {
85
+ dragged.point.m = 10000.0;
86
+
87
+ if (nodeSelected) {
88
+ nodeSelected(selected.node);
89
+ }
90
+ }
91
+
92
+ renderer.start();
93
+ });
94
+
95
+ // Basic double click handler
96
+ jQuery(canvas).dblclick(function(e) {
97
+ var pos = jQuery(this).offset();
98
+ var p = fromScreen({x: e.pageX - pos.left, y: e.pageY - pos.top});
99
+ selected = layout.nearest(p);
100
+ node = selected.node;
101
+ if (node && node.data && node.data.ondoubleclick) {
102
+ node.data.ondoubleclick();
103
+ }
104
+ });
105
+
106
+ jQuery(canvas).mousemove(function(e) {
107
+ var pos = jQuery(this).offset();
108
+ var p = fromScreen({x: e.pageX - pos.left, y: e.pageY - pos.top});
109
+ nearest = layout.nearest(p);
110
+
111
+ if (dragged !== null && dragged.node !== null) {
112
+ dragged.point.p.x = p.x;
113
+ dragged.point.p.y = p.y;
114
+ }
115
+
116
+ renderer.start();
117
+ });
118
+
119
+ jQuery(window).bind('mouseup',function(e) {
120
+ dragged = null;
121
+ });
122
+
123
+ Springy.Node.prototype.getWidth = function() {
124
+ var text = (this.data.label !== undefined) ? this.data.label : this.id;
125
+ if (this._width && this._width[text])
126
+ return this._width[text];
127
+
128
+ ctx.save();
129
+ ctx.font = "16px Verdana, sans-serif";
130
+ var width = ctx.measureText(text).width + 10;
131
+ ctx.restore();
132
+
133
+ this._width || (this._width = {});
134
+ this._width[text] = width;
135
+
136
+ return width;
137
+ };
138
+
139
+ Springy.Node.prototype.getHeight = function() {
140
+ return 20;
141
+ };
142
+
143
+ var renderer = this.renderer = new Springy.Renderer(layout,
144
+ function clear() {
145
+ ctx.clearRect(0,0,canvas.width,canvas.height);
146
+ },
147
+ function drawEdge(edge, p1, p2) {
148
+ var x1 = toScreen(p1).x;
149
+ var y1 = toScreen(p1).y;
150
+ var x2 = toScreen(p2).x;
151
+ var y2 = toScreen(p2).y;
152
+
153
+ var direction = new Springy.Vector(x2-x1, y2-y1);
154
+ var normal = direction.normal().normalise();
155
+
156
+ var from = graph.getEdges(edge.source, edge.target);
157
+ var to = graph.getEdges(edge.target, edge.source);
158
+
159
+ var total = from.length + to.length;
160
+
161
+ // Figure out edge's position in relation to other edges between the same nodes
162
+ var n = 0;
163
+ for (var i=0; i<from.length; i++) {
164
+ if (from[i].id === edge.id) {
165
+ n = i;
166
+ }
167
+ }
168
+
169
+ var spacing = 6.0;
170
+
171
+ // Figure out how far off center the line should be drawn
172
+ var offset = normal.multiply(-((total - 1) * spacing)/2.0 + (n * spacing));
173
+
174
+ var s1 = toScreen(p1).add(offset);
175
+ var s2 = toScreen(p2).add(offset);
176
+
177
+ var boxWidth = edge.target.getWidth();
178
+ var boxHeight = edge.target.getHeight();
179
+
180
+ var intersection = intersect_line_box(s1, s2, {x: x2-boxWidth/2.0, y: y2-boxHeight/2.0}, boxWidth, boxHeight);
181
+
182
+ if (!intersection) {
183
+ intersection = s2;
184
+ }
185
+
186
+ var stroke = (edge.data.color !== undefined) ? edge.data.color : '#000000';
187
+
188
+ var arrowWidth;
189
+ var arrowLength;
190
+
191
+ var weight = (edge.data.weight !== undefined) ? edge.data.weight : 1.0;
192
+
193
+ ctx.lineWidth = Math.max(weight * 2, 0.1);
194
+ arrowWidth = 1 + ctx.lineWidth;
195
+ arrowLength = 8;
196
+
197
+ var directional = (edge.data.directional !== undefined) ? edge.data.directional : true;
198
+
199
+ // line
200
+ var lineEnd;
201
+ if (directional) {
202
+ lineEnd = intersection.subtract(direction.normalise().multiply(arrowLength * 0.5));
203
+ } else {
204
+ lineEnd = s2;
205
+ }
206
+
207
+ ctx.strokeStyle = stroke;
208
+ ctx.beginPath();
209
+ ctx.moveTo(s1.x, s1.y);
210
+ ctx.lineTo(lineEnd.x, lineEnd.y);
211
+ ctx.stroke();
212
+
213
+ // arrow
214
+ if (directional) {
215
+ ctx.save();
216
+ ctx.fillStyle = stroke;
217
+ ctx.translate(intersection.x, intersection.y);
218
+ ctx.rotate(Math.atan2(y2 - y1, x2 - x1));
219
+ ctx.beginPath();
220
+ ctx.moveTo(-arrowLength, arrowWidth);
221
+ ctx.lineTo(0, 0);
222
+ ctx.lineTo(-arrowLength, -arrowWidth);
223
+ ctx.lineTo(-arrowLength * 0.8, -0);
224
+ ctx.closePath();
225
+ ctx.fill();
226
+ ctx.restore();
227
+ }
228
+
229
+ // label
230
+ if (edge.data.label !== undefined) {
231
+ text = edge.data.label
232
+ ctx.save();
233
+ ctx.textAlign = "center";
234
+ ctx.textBaseline = "top";
235
+ ctx.font = "10px Helvetica, sans-serif";
236
+ ctx.fillStyle = "#5BA6EC";
237
+ ctx.fillText(text, (x1+x2)/2, (y1+y2)/2);
238
+ ctx.restore();
239
+ }
240
+
241
+ },
242
+ function drawNode(node, p) {
243
+ var s = toScreen(p);
244
+
245
+ ctx.save();
246
+
247
+ var boxWidth = node.getWidth();
248
+ var boxHeight = node.getHeight();
249
+
250
+ // clear background
251
+ ctx.clearRect(s.x - boxWidth/2, s.y - 10, boxWidth, 20);
252
+
253
+ // fill background
254
+ if (selected !== null && nearest.node !== null && selected.node.id === node.id) {
255
+ ctx.fillStyle = "#FFFFE0";
256
+ } else if (nearest !== null && nearest.node !== null && nearest.node.id === node.id) {
257
+ ctx.fillStyle = "#EEEEEE";
258
+ } else {
259
+ ctx.fillStyle = "#FFFFFF";
260
+ }
261
+ ctx.fillRect(s.x - boxWidth/2, s.y - 10, boxWidth, 20);
262
+
263
+ ctx.textAlign = "left";
264
+ ctx.textBaseline = "top";
265
+ ctx.font = "16px Verdana, sans-serif";
266
+ ctx.fillStyle = "#000000";
267
+ ctx.font = "16px Verdana, sans-serif";
268
+ var text = (node.data.label !== undefined) ? node.data.label : node.id;
269
+ ctx.fillText(text, s.x - boxWidth/2 + 5, s.y - 8);
270
+
271
+ ctx.restore();
272
+ }
273
+ );
274
+
275
+ renderer.start();
276
+
277
+ // helpers for figuring out where to draw arrows
278
+ function intersect_line_line(p1, p2, p3, p4) {
279
+ var denom = ((p4.y - p3.y)*(p2.x - p1.x) - (p4.x - p3.x)*(p2.y - p1.y));
280
+
281
+ // lines are parallel
282
+ if (denom === 0) {
283
+ return false;
284
+ }
285
+
286
+ var ua = ((p4.x - p3.x)*(p1.y - p3.y) - (p4.y - p3.y)*(p1.x - p3.x)) / denom;
287
+ var ub = ((p2.x - p1.x)*(p1.y - p3.y) - (p2.y - p1.y)*(p1.x - p3.x)) / denom;
288
+
289
+ if (ua < 0 || ua > 1 || ub < 0 || ub > 1) {
290
+ return false;
291
+ }
292
+
293
+ return new Springy.Vector(p1.x + ua * (p2.x - p1.x), p1.y + ua * (p2.y - p1.y));
294
+ }
295
+
296
+ function intersect_line_box(p1, p2, p3, w, h) {
297
+ var tl = {x: p3.x, y: p3.y};
298
+ var tr = {x: p3.x + w, y: p3.y};
299
+ var bl = {x: p3.x, y: p3.y + h};
300
+ var br = {x: p3.x + w, y: p3.y + h};
301
+
302
+ var result;
303
+ if (result = intersect_line_line(p1, p2, tl, tr)) { return result; } // top
304
+ if (result = intersect_line_line(p1, p2, tr, br)) { return result; } // right
305
+ if (result = intersect_line_line(p1, p2, br, bl)) { return result; } // bottom
306
+ if (result = intersect_line_line(p1, p2, bl, tl)) { return result; } // left
307
+
308
+ return false;
309
+ }
310
+
311
+ return this;
312
+ }
313
+
314
+ })();
@@ -0,0 +1,11 @@
1
+ function load_data(graph) {
2
+ var deps = {}
3
+ <% deps.each do |name, dep| %>
4
+ deps[<%= name.inspect %>] = graph.newNode({label: <%= name.inspect %>});<% end %>
5
+
6
+ <% deps.each do |name, dep| %><% depname = name.gsub(/ /, "_") %>
7
+ <% dep.___dependencies.each do |dependency| %>
8
+ if (deps[<%= dependency.inspect %>] !== undefined)
9
+ graph.newEdge(deps[<%= name.inspect %>], deps[<%= dependency.inspect %>]);
10
+ <% end %> <% end %>
11
+ }
@@ -0,0 +1,25 @@
1
+ <!doctype html>
2
+ <html lang=en>
3
+ <head>
4
+ <meta charset=utf-8>
5
+ <title></title>
6
+ <script src="vendor/jquery-1.9.1.js"></script>
7
+ <script src="vendor/springy.js"></script>
8
+ <script src="vendor/springyui.js"></script>
9
+ <script src="data.js"></script>
10
+ </head>
11
+ <body>
12
+ <canvas id="dependency_graph" width="20" height="20" />
13
+ </body>
14
+ <script>
15
+ $(document).ready(function() {
16
+ var graph_cvs = document.getElementById('dependency_graph');
17
+ graph_cvs.width = document.width;
18
+ graph_cvs.height = document.height;
19
+ var graph = new Springy.Graph();
20
+ load_data(graph);
21
+ $('#dependency_graph').springy({graph: graph});
22
+ });
23
+ </script>
24
+ </html>
25
+
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: babushka-viz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Richo Healey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ - !binary |-
13
+ LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURORENDQWh5Z0F3SUJB
14
+ Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREJBTVE0d0RBWURWUVFEREFWeWFX
15
+ Tm8KYnpFWk1CY0dDZ21TSm9tVDhpeGtBUmtXQ1hCemVXTm9NSFJwYXpFVE1C
16
+ RUdDZ21TSm9tVDhpeGtBUmtXQTI1bApkREFlRncweE1qRXdNall4TXpNMU1U
17
+ WmFGdzB4TXpFd01qWXhNek0xTVRaYU1FQXhEakFNQmdOVkJBTU1CWEpwClky
18
+ aHZNUmt3RndZS0NaSW1pWlB5TEdRQkdSWUpjSE41WTJnd2RHbHJNUk13RVFZ
19
+ S0NaSW1pWlB5TEdRQkdSWUQKYm1WME1JSUJJakFOQmdrcWhraUc5dzBCQVFF
20
+ RkFBT0NBUThBTUlJQkNnS0NBUUVBeEJ5Y1ZYYU1QMWpmWHRGTwpqL3E4SEQ1
21
+ WGU1Lzl1K29kK0lSYUJDNUdDZnRPVlI3WG13T04vTThoVms5ZmRtSG5TYzhI
22
+ RGNBclNzVE55RHlJCitnck1YVDBUU3pkNnpydUc4eG5IWlNqR0NvNmd4cHZo
23
+ YnBMZzZtRk9WaldCTXQwL2RWK3R6ZlNOZENJK3NYaUgKYW1Zem14aWJFUVBN
24
+ MXhnWlBwaFV1RURkcldzMUNPVmxBWk80ekEyVTZYYUZHVlhLQjRDT1VkeGVI
25
+ bGNoV0g3dApPR1J2OFFBcTZZRG0wUkRKYXlyTTA5MmJ2UUZXSFE0anJ6MUxp
26
+ a0J1c2lJYlVMOGFnYmNMVVBLYXc3VVFDWWEvCmFZMUZEQ0pGTEZ1SmhUaGdS
27
+ dWZGSDB0N09XclRVYUJzQ0tqK05kSnZwMlk3emNQOTFaV1FhZll0WTR2enQ0
28
+ RzQKZDU3VHdRSURBUUFCb3prd056QUpCZ05WSFJNRUFqQUFNQjBHQTFVZERn
29
+ UVdCQlEvRitqak9lcVBveTNyWks5QQplaXBqR1dpQVpUQUxCZ05WSFE4RUJB
30
+ TUNCTEF3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUJoa3drMTVUU3h0ClFO
31
+ azY5SFd6ckFObjRjcm9MVjN5VVBXYzdUTDZJU25nRzUxRytwaUF1cS96a2Q1
32
+ UVhpcmExZnBna284N003b3kKMElIRGFsc0pGR3ZQQUFhNnJZSTRQcG1jZUhv
33
+ UDl1bzhpRktpNEhRZDJIanFqR3dKM2ZzcnpTNkdzYWhiaDFRcwpNd1JMVkJ5
34
+ N1RWMkNiMDhRVWxCOG85TjRWR2dTaGdsN3RnRlZXQ1UrWFZVQmM4WGZmcVRs
35
+ aE9iU0N6U0taNXRaCm51OHViQkV2RncwdXpHSkdRc0RoajFieHlpNUR1Yksy
36
+ WE94VTdHci9meUJWeHlzOUUwV01VUEVldDZseis2bGEKRVpvb0RGQTRZbU1J
37
+ Zlc4RnZqMi9UM1Yvc0wxdkpTRENkVHY3RUNkb1g1c25RbVR4RDlwRnNVbXhM
38
+ ZmlKL01GTQppaXcrT1B0dmxzST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0t
39
+ LQo=
40
+ date: 2013-03-25 00:00:00.000000000 Z
41
+ dependencies: []
42
+ description: description
43
+ email:
44
+ - richo@psych0tik.net
45
+ executables:
46
+ - babushka-viz
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - .gitignore
51
+ - README.md
52
+ - babushka-viz.gemspec
53
+ - bin/babushka-viz
54
+ - lib/babushka-viz/deps.rb
55
+ - public/vendor/jquery-1.9.1.js
56
+ - public/vendor/springy.js
57
+ - public/vendor/springyui.js
58
+ - template/data.js.erb
59
+ - template/index.html.erb
60
+ homepage: http://github.com/richo/babushka-viz
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.24
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: description
84
+ test_files: []
@@ -0,0 +1,3 @@
1
+ Mt
2
+ _m�=�z���:c<h��!�ĺX�(�=K�VC�����#�BN�z$��6�b�!=��F����)��f�/y���3��|�/SCx7�d���LJ��o s'�\)���l^P�$��
3
+ [b�p��