gerbilcharts 0.2.13 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +35 -0
- data/Manifest.txt +8 -0
- data/README.txt +8 -8
- data/lib/gerbilcharts/charts.rb +3 -0
- data/lib/gerbilcharts/charts/bubble_chart.rb +30 -0
- data/lib/gerbilcharts/charts/conversation_ring.rb +31 -0
- data/lib/gerbilcharts/charts/line_chart.rb +1 -0
- data/lib/gerbilcharts/charts/matrix_chart.rb +32 -0
- data/lib/gerbilcharts/charts/square_line_chart.rb +7 -0
- data/lib/gerbilcharts/models.rb +1 -0
- data/lib/gerbilcharts/models/bucketized_timeseries_graph_model.rb +1 -1
- data/lib/gerbilcharts/models/graph_model_group.rb +19 -2
- data/lib/gerbilcharts/models/matrix_model.rb +85 -0
- data/lib/gerbilcharts/models/monotonous_graph_model.rb +5 -1
- data/lib/gerbilcharts/models/presets.rb +18 -11
- data/lib/gerbilcharts/models/raw_range.rb +1 -1
- data/lib/gerbilcharts/models/round_range.rb +3 -1
- data/lib/gerbilcharts/models/round_time_range.rb +19 -29
- data/lib/gerbilcharts/models/sampled_timeseries_graph_model.rb +1 -1
- data/lib/gerbilcharts/public/brushmetal.css +123 -74
- data/lib/gerbilcharts/public/gerbil.js +104 -64
- data/lib/gerbilcharts/surfaces.rb +3 -0
- data/lib/gerbilcharts/surfaces/bubble_surface.rb +105 -0
- data/lib/gerbilcharts/surfaces/chart.rb +4 -2
- data/lib/gerbilcharts/surfaces/conversation_ring.rb +64 -0
- data/lib/gerbilcharts/surfaces/detailed_legend.rb +35 -13
- data/lib/gerbilcharts/surfaces/graph_element.rb +8 -1
- data/lib/gerbilcharts/surfaces/grid.rb +8 -2
- data/lib/gerbilcharts/surfaces/horizontal_axis.rb +12 -3
- data/lib/gerbilcharts/surfaces/horizontal_time_axis.rb +5 -4
- data/lib/gerbilcharts/surfaces/impulse_surface.rb +1 -1
- data/lib/gerbilcharts/surfaces/legend.rb +43 -6
- data/lib/gerbilcharts/surfaces/mark_band.rb +17 -1
- data/lib/gerbilcharts/surfaces/matrix_surface.rb +87 -0
- data/lib/gerbilcharts/surfaces/pie_surface.rb +109 -96
- data/lib/gerbilcharts/surfaces/rect.rb +18 -0
- data/lib/gerbilcharts/surfaces/stacked_area_surface.rb +42 -2
- data/lib/gerbilcharts/surfaces/stacked_grid.rb +1 -3
- data/lib/gerbilcharts/surfaces/title_panel.rb +7 -2
- data/lib/gerbilcharts/surfaces/tracker.rb +4 -1
- data/lib/gerbilcharts/surfaces/vertical_axis.rb +2 -2
- data/lib/gerbilcharts/svgdc.rb +1 -0
- data/lib/gerbilcharts/svgdc/css_inliner.rb +2 -2
- data/lib/gerbilcharts/svgdc/svg_ellipse.rb +21 -0
- data/lib/gerbilcharts/svgdc/svg_polygon.rb +19 -0
- data/lib/gerbilcharts/svgdc/svgdc.rb +4 -1
- data/lib/gerbilcharts/version.rb +2 -3
- data/test/test_bar.rb +1 -1
- data/test/test_bubble.rb +52 -0
- data/test/test_conversation.rb +34 -0
- data/test/test_lines.rb +3 -3
- data/test/test_matrix.rb +34 -0
- data/test/test_noob.rb +9 -6
- data/test/test_pie.rb +2 -2
- data/test/test_ranges.rb +15 -2
- data/test/test_sa.rb +88 -0
- metadata +14 -2
@@ -19,14 +19,22 @@ function OpacityDown(mouseover_evt)
|
|
19
19
|
var obj=mouseover_evt.target;
|
20
20
|
obj.style.setProperty("opacity","0.5","");
|
21
21
|
}
|
22
|
-
|
23
|
-
|
24
22
|
function OpacityUp(mouseout_evt)
|
25
23
|
{
|
26
24
|
var obj=mouseout_evt.target;
|
27
25
|
obj.style.setProperty("opacity","1.0","");
|
28
26
|
}
|
29
|
-
|
27
|
+
function ToggleVisibility(id)
|
28
|
+
{
|
29
|
+
var worker = function(ai) {
|
30
|
+
var cv=ai.getAttributeNS(null,"visibility");
|
31
|
+
ai.setAttributeNS(null,"visibility",cv=="hidden"?"":"hidden");
|
32
|
+
$("lbx"+id).setAttributeNS(null,"fill",cv=="hidden"?"gray":"red");
|
33
|
+
};
|
34
|
+
|
35
|
+
$$("#item"+id).each(worker);
|
36
|
+
$$("#lineitem"+id).each(worker);
|
37
|
+
}
|
30
38
|
function GerbilNavigate()
|
31
39
|
{
|
32
40
|
window.top.location='/dashboard/show';
|
@@ -86,6 +94,20 @@ function showDetailedLegend()
|
|
86
94
|
l_show.setAttributeNS(null, 'visibility', 'visible');
|
87
95
|
}
|
88
96
|
}
|
97
|
+
// Move legend panel
|
98
|
+
function shiftLegend(xoffset)
|
99
|
+
{
|
100
|
+
var l_det = SVGDocument.getElementById("legendpanel_detail");
|
101
|
+
if (l_det)
|
102
|
+
{
|
103
|
+
l_det.setAttributeNS(null, 'transform', 'translate('+xoffset+')');
|
104
|
+
}
|
105
|
+
var l_mini= SVGDocument.getElementById("legendpanel_mini");
|
106
|
+
if (l_mini)
|
107
|
+
{
|
108
|
+
l_mini.setAttributeNS(null, 'transform', 'translate('+xoffset+')');
|
109
|
+
}
|
110
|
+
}
|
89
111
|
|
90
112
|
// The chart needs to fill in the following options
|
91
113
|
// axurl , response will either do noop/full/delta replacement
|
@@ -108,17 +130,17 @@ function SvgAjaxUpdate()
|
|
108
130
|
});
|
109
131
|
hContext.unset('_object');
|
110
132
|
|
111
|
-
// console.log ("URL = "+ url );
|
112
133
|
new Ajax.Request(url, {
|
113
134
|
method: 'post',
|
114
|
-
parameters: {
|
135
|
+
parameters: {'resource': hContext['resource']},
|
115
136
|
onSuccess: function(transport) {
|
116
|
-
updateSVG(transport.responseXML)
|
137
|
+
updateSVG(transport.responseXML);
|
117
138
|
}
|
118
139
|
});
|
119
140
|
|
141
|
+
SVGRoot.setAttributeNS(null, 'lastupdategmt', parseInt(new Date().getTime()/1000) );
|
120
142
|
}
|
121
|
-
// For WebTrisul 1.
|
143
|
+
// For WebTrisul 1.x, we don't yet support delta replace,
|
122
144
|
// full replace seems to be fast enough (caching on server side)
|
123
145
|
function updateSVG(node)
|
124
146
|
{
|
@@ -162,10 +184,9 @@ function Uninit(evt)
|
|
162
184
|
hContext[at.localName]=at.nodeValue;
|
163
185
|
});
|
164
186
|
|
165
|
-
// console.log ("URL = "+ url );
|
166
187
|
new Ajax.Request("/axupdate/gerbilUnload", {
|
167
188
|
method: 'post',
|
168
|
-
parameters: {
|
189
|
+
parameters: {'resource': hContext['resource']}
|
169
190
|
});
|
170
191
|
}
|
171
192
|
|
@@ -198,7 +219,7 @@ function Init(evt)
|
|
198
219
|
// for Adobe SVG later
|
199
220
|
// setTimeout("SvgAjaxUpdate()",parseInt(ajaxInterval));
|
200
221
|
}
|
201
|
-
}
|
222
|
+
}
|
202
223
|
|
203
224
|
|
204
225
|
function GetTrueCoords(evt)
|
@@ -208,69 +229,69 @@ function GetTrueCoords(evt)
|
|
208
229
|
var translation = SVGRoot.currentTranslate;
|
209
230
|
TrueCoords.x = (evt.clientX - translation.x)/newScale;
|
210
231
|
TrueCoords.y = (evt.clientY - translation.y)/newScale;
|
211
|
-
}
|
232
|
+
}
|
212
233
|
|
213
234
|
|
214
235
|
function HideTooltip( evt )
|
215
236
|
{
|
216
237
|
toolTip.setAttributeNS(null, 'visibility', 'hidden');
|
217
|
-
}
|
238
|
+
}
|
218
239
|
|
219
240
|
|
220
241
|
function ShowTooltip( evt )
|
221
242
|
{
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
243
|
+
// bail out early, if same target
|
244
|
+
var targetElement = evt.target;
|
245
|
+
if ( lastElement == targetElement )
|
246
|
+
{
|
247
|
+
return
|
248
|
+
}
|
228
249
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
250
|
+
// bail out early, if no 'gerbiltooltipX' tags
|
251
|
+
// tooltip1 is the heading (appears in bold face)
|
252
|
+
// tooltip2 is the tip text
|
253
|
+
var tooltip1 = '';
|
254
|
+
var tooltip2 = '';
|
255
|
+
tooltip1 = targetElement.getAttributeNS(null, 'gerbiltooltip1');
|
256
|
+
tooltip2 = targetElement.getAttributeNS(null, 'gerbiltooltip2');
|
257
|
+
if (tooltip1=='' && tooltip2 == '')
|
258
|
+
{
|
259
|
+
return;
|
260
|
+
}
|
240
261
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
262
|
+
// Positon the tooltip box relative to the mouse pos
|
263
|
+
GetTrueCoords( evt );
|
264
|
+
var tipScale = 1/SVGRoot.currentScale;
|
265
|
+
var textWidth = 0;
|
266
|
+
var tspanWidth = 0;
|
267
|
+
var boxHeight = 20;
|
268
|
+
tipBox.setAttributeNS(null, 'transform', 'scale(' + tipScale + ',' + tipScale + ')' );
|
269
|
+
tipText.setAttributeNS(null, 'transform', 'scale(' + tipScale + ',' + tipScale + ')' );
|
249
270
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
271
|
+
// Values for tooltip text
|
272
|
+
tipTitle.firstChild.nodeValue = tooltip1;
|
273
|
+
tipTitle.setAttributeNS(null, 'display', 'inline' );
|
274
|
+
tipDesc.firstChild.nodeValue = tooltip2;
|
275
|
+
tipDesc.setAttributeNS(null, 'display', 'inline' );
|
255
276
|
|
256
277
|
|
257
|
-
|
278
|
+
// Box size
|
258
279
|
var outline = tipText.getBBox();
|
259
280
|
tipBox.setAttributeNS(null, 'width', Number(outline.width) + 10);
|
260
|
-
tipBox.setAttributeNS(null, 'height', Number(outline.height));
|
281
|
+
tipBox.setAttributeNS(null, 'height', Number(outline.height) + 10);
|
261
282
|
|
262
283
|
|
263
284
|
// Update position (keep tooltip inside client area ! )
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
285
|
+
var yPos = TrueCoords.y + (10 * tipScale);
|
286
|
+
if (yPos+Number(outline.height)>SVGRoot.height.baseVal.value)
|
287
|
+
{
|
288
|
+
yPos = SVGRoot.height.baseVal.value - Number(outline.height)
|
289
|
+
}
|
269
290
|
var xPos = TrueCoords.x + (10 * tipScale);
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
291
|
+
if (xPos+Number(outline.width)>SVGRoot.width.baseVal.value)
|
292
|
+
{
|
293
|
+
xPos = SVGRoot.width.baseVal.value - Number(outline.width)
|
294
|
+
}
|
274
295
|
|
275
296
|
toolTip.setAttributeNS(null, 'transform', 'translate(' + xPos + ',' + yPos + ')');
|
276
297
|
toolTip.setAttributeNS(null, 'visibility', 'visible');
|
@@ -310,13 +331,19 @@ function TrackerMouseDown( evt )
|
|
310
331
|
|
311
332
|
// compute begin state
|
312
333
|
pTrackerData = SVGDocument.getElementById('gtrackerdata');
|
313
|
-
nTrackScale =
|
334
|
+
nTrackScale = parseFloat(pTrackerData.getAttributeNS(null,"gerb_scale"));
|
314
335
|
var from_secs = parseInt(pTrackerData.getAttributeNS(null,"gerb_fromts"));
|
315
|
-
|
336
|
+
var server_tz_offset = parseInt(pTrackerData.getAttributeNS(null,"gerb_tzoffset"));
|
337
|
+
var client_tz_offset = new Date().getTimezoneOffset() * 60;
|
338
|
+
|
339
|
+
// javascript returns utc-local, ruby returns local-utc (so the '+' )
|
340
|
+
tz_off = server_tz_offset + client_tz_offset;
|
341
|
+
tz_name= pTrackerData.getAttributeNS(null,"gerb_tzname");
|
342
|
+
|
316
343
|
// clicked to time delta
|
317
344
|
var xbegin = parseInt(SVGDocument.getElementById('trackerpanel').getAttributeNS(null,"x"));
|
318
345
|
pTrackFromTS = new Date();
|
319
|
-
pTrackFromTS.setTime(1000* (from_secs + (nTrackBegin-xbegin)*nTrackScale));
|
346
|
+
pTrackFromTS.setTime(1000* (tz_off + from_secs + (nTrackBegin-xbegin)*nTrackScale));
|
320
347
|
|
321
348
|
// text svg elements
|
322
349
|
pTrackTextFromTS=SVGDocument.getElementById('trackertextfromts');
|
@@ -326,46 +353,59 @@ function TrackerMouseDown( evt )
|
|
326
353
|
pGTrackingRect.setAttributeNS(null,"visibility","hidden");
|
327
354
|
pTrackingText.setAttributeNS(null,"visibility","hidden");
|
328
355
|
|
356
|
+
evt.preventDefault();
|
357
|
+
|
329
358
|
}
|
330
359
|
|
331
360
|
function TrackerMouseMove(evt)
|
332
361
|
{
|
362
|
+
|
333
363
|
if (fTracking==2 && evt.clientX > nTrackBegin)
|
334
364
|
{
|
365
|
+
|
335
366
|
var delta = nTrackCurrent-nTrackBegin;
|
336
367
|
var mid = nTrackBegin+(delta)/2;
|
337
368
|
nTrackCurrent=evt.clientX;
|
369
|
+
|
338
370
|
pTrackingRect.setAttributeNS(null,"width",delta);
|
339
371
|
pTrackingText.setAttributeNS(null,"transform","translate(" + mid + ')');
|
340
|
-
|
372
|
+
|
341
373
|
// text box
|
342
374
|
var szwin = FormatSecs(delta*nTrackScale)
|
343
|
-
var szbegin = "Starting : " + pTrackFromTS.toLocaleString();
|
375
|
+
var szbegin = "Starting : " + pTrackFromTS.toLocaleString() + " " + tz_name;
|
344
376
|
pTrackTextInterval.firstChild.nodeValue = szwin;
|
345
377
|
pTrackTextFromTS.firstChild.nodeValue = szbegin;
|
378
|
+
|
346
379
|
}
|
347
|
-
else if (fTracking==1
|
380
|
+
else if (fTracking==1 && (evt.clientX-nTrackBegin) > 5 )
|
348
381
|
{
|
349
382
|
// we need to move atleast 5 pixels to turn on tracking
|
350
383
|
fTracking=2;
|
351
|
-
|
352
|
-
// visibility on
|
384
|
+
|
385
|
+
// visibility on
|
353
386
|
pGTrackingRect.setAttributeNS(null,"visibility","visible");
|
354
387
|
pTrackingText.setAttributeNS(null,"visibility","visible");
|
388
|
+
|
389
|
+
parent.$('drillmod_tools').hide();
|
355
390
|
}
|
391
|
+
|
356
392
|
}
|
393
|
+
|
357
394
|
function TrackerMouseUp(evt)
|
358
395
|
{
|
396
|
+
|
359
397
|
if (fTracking==2)
|
360
398
|
{
|
361
399
|
pTrackingRect=null;
|
362
400
|
nTrackEnd=evt.clientX;
|
363
401
|
|
364
402
|
pTrackerData.setAttributeNS(null,"gerb_selsecs",(nTrackEnd-nTrackBegin)*nTrackScale);
|
365
|
-
pTrackerData.setAttributeNS(null,"gerb_selts", pTrackFromTS.getTime()/1000);
|
403
|
+
pTrackerData.setAttributeNS(null,"gerb_selts", pTrackFromTS.getTime()/1000-tz_off);
|
366
404
|
|
367
405
|
}
|
368
406
|
fTracking=0;
|
407
|
+
parent.$('drillmod_tools').show();
|
408
|
+
|
369
409
|
}
|
370
410
|
|
371
411
|
function FormatSecs(secs)
|
@@ -375,7 +415,7 @@ function FormatSecs(secs)
|
|
375
415
|
} else if (secs>3600) {
|
376
416
|
return "" + Math.floor(secs/3600) + " Hrs " + Math.round((secs%3600)/60) + " Mins";
|
377
417
|
} else if (secs>60) {
|
378
|
-
return "" + Math.floor(secs/60) + " Mins " + secs%60 + " Secs";
|
418
|
+
return "" + Math.floor(secs/60) + " Mins " + Math.round(secs%60) + " Secs";
|
379
419
|
}
|
380
|
-
return "" + secs + " Secs";
|
420
|
+
return "" + Math.round(secs) + " Secs";
|
381
421
|
}
|
@@ -32,3 +32,6 @@ require 'gerbilcharts/surfaces/stacked_area_surface'
|
|
32
32
|
require 'gerbilcharts/surfaces/surface_background'
|
33
33
|
require 'gerbilcharts/surfaces/tracker'
|
34
34
|
require 'gerbilcharts/surfaces/square_line_surface'
|
35
|
+
require 'gerbilcharts/surfaces/matrix_surface'
|
36
|
+
require 'gerbilcharts/surfaces/conversation_ring'
|
37
|
+
require 'gerbilcharts/surfaces/bubble_surface'
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
#= Bubble Surface
|
4
|
+
# Data point represented by bubbles using a log scale count
|
5
|
+
# Control the color,thickness of the line via the stylesheet item lineitem1, lineitem2 etc
|
6
|
+
# Eg 27,500 = 2x10K bub + 7x1K bub + 5 100 bub (total = 14 bubbles)
|
7
|
+
#
|
8
|
+
# Supported global options
|
9
|
+
#
|
10
|
+
# [+scaling+] :auto, :auto_y0
|
11
|
+
#
|
12
|
+
class BubbleSurface < Surface
|
13
|
+
|
14
|
+
BUBGRAINS = [1e+9,1e+8,1e+7,1000000,100000,10000,1000,100,10,1]
|
15
|
+
SHAPESZ = [40, 36, 35, 34, 31, 30, 20, 16, 12,8]
|
16
|
+
RSCALE = 0.50
|
17
|
+
|
18
|
+
def initialize(opts={})
|
19
|
+
super(opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def int_render(g)
|
23
|
+
rx = parent.modelgroup.effective_round_range_x
|
24
|
+
ry = parent.modelgroup.cumulative_sweep_round_range_y0
|
25
|
+
|
26
|
+
# ajax if used
|
27
|
+
if parent.usesAjax?
|
28
|
+
set_ajaxSurfaceContext(rx.rmax,ry.rmax,"SA")
|
29
|
+
end
|
30
|
+
|
31
|
+
# prepare models for sweeping
|
32
|
+
sweep_pos= rx.rmin
|
33
|
+
sweep_to = rx.rmax
|
34
|
+
modnames = []
|
35
|
+
parent.modelgroup.each_model do | mod|
|
36
|
+
mod.begin_sweep
|
37
|
+
modnames << mod.name
|
38
|
+
end
|
39
|
+
|
40
|
+
# sweep interval
|
41
|
+
sweep_interval = parent.modelgroup.sweep_interval
|
42
|
+
|
43
|
+
rbub=@bounds.clone
|
44
|
+
rbub.clip_l(20)
|
45
|
+
|
46
|
+
# perform the sweep
|
47
|
+
while (sweep_pos<=sweep_to)
|
48
|
+
|
49
|
+
allshapes = []
|
50
|
+
xpos = scale_x sweep_pos,rx
|
51
|
+
rbub.translate_x xpos
|
52
|
+
|
53
|
+
parent.modelgroup.each_model_with_index do | mod, i|
|
54
|
+
val = mod.sweep(sweep_pos)
|
55
|
+
allshapes << valtocircles(val)
|
56
|
+
end
|
57
|
+
|
58
|
+
allshapes.each_with_index do |ai,i|
|
59
|
+
|
60
|
+
opts = {:id => "item#{i}"}
|
61
|
+
opts.store(:fill,color_for_id(i)) if i>10
|
62
|
+
|
63
|
+
if parent.get_global_option(:auto_tooltips,false)
|
64
|
+
opts.store(:gerbiltooltip1, modnames[i])
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
ai.each do |shp|
|
69
|
+
shp.x = rbub.left + rand*(rbub.width)
|
70
|
+
shp.y = rbub.bottom - rand*(rbub.height*0.75)
|
71
|
+
g.addshape(shp, opts)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
sweep_pos += sweep_interval
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# vartoradii
|
82
|
+
def valtocircles(val)
|
83
|
+
|
84
|
+
splitup=BUBGRAINS.collect do |grain_size|
|
85
|
+
n=(val/grain_size)
|
86
|
+
val = val%grain_size
|
87
|
+
(n*RSCALE).to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
ret=[]
|
92
|
+
shapes=SHAPESZ.each_with_index do |s,i|
|
93
|
+
splitup[i].times do |t|
|
94
|
+
ret << GerbilCharts::SVGDC::SVGCircle.new(0, 0, s)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
ret
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -67,6 +67,8 @@ class Chart < GraphElement
|
|
67
67
|
|
68
68
|
def render(ropts={})
|
69
69
|
svgdc = GerbilCharts::SVGDC::SVGDC.new(@bounds.width, @bounds.height)
|
70
|
+
|
71
|
+
svgdc.enable_tooltips get_global_option(:auto_tooltips,false)
|
70
72
|
|
71
73
|
dolayout if @needslayout
|
72
74
|
|
@@ -79,8 +81,8 @@ class Chart < GraphElement
|
|
79
81
|
end
|
80
82
|
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
+
# filters, javascripts, stylesheets
|
85
|
+
@filters.each { |f| svgdc.add_filter(f) }
|
84
86
|
@javascripts.each { |scr| svgdc.add_javascriptfile(scr) }
|
85
87
|
@stylesheets.each { |css| svgdc.add_stylesheetfile(css) }
|
86
88
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module GerbilCharts::Surfaces
|
2
|
+
|
3
|
+
# Matrix Surface
|
4
|
+
# Conversation Chart is drawn
|
5
|
+
#
|
6
|
+
class ConversationRing < Surface
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
super(opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
def int_render(g)
|
13
|
+
# any filters ?
|
14
|
+
if parent.get_global_option(:filter,false)
|
15
|
+
g.curr_win.add_options({:filter => "url(##{parent.get_global_option(:filter,false)})" })
|
16
|
+
end
|
17
|
+
|
18
|
+
# Draw an outer circle
|
19
|
+
center_x = (@bounds.width/2)
|
20
|
+
center_y = (@bounds.height/2) + @bounds.top + 10
|
21
|
+
radius_x = (@bounds.width/2 - 35)
|
22
|
+
radius_y = (@bounds.height/2 - 15)
|
23
|
+
g.addshape(GerbilCharts::SVGDC::SVGEllipse.new(center_x,center_y,radius_x,radius_y), :fill => '#FFD' )
|
24
|
+
|
25
|
+
|
26
|
+
parent.modelgroup.hash.each_pair do |key,value|
|
27
|
+
angle = 360/value.length
|
28
|
+
tot_angle = 0
|
29
|
+
# Draw the center circle
|
30
|
+
radius1 = 15
|
31
|
+
opts = {:id => "item0"}
|
32
|
+
g.addshape(GerbilCharts::SVGDC::SVGCircle.new(center_x,center_y,radius1),opts)
|
33
|
+
g.textout(center_x-30,center_y-20,key,:class => 'elementlabel')
|
34
|
+
|
35
|
+
# Draw the remaining circles proportion to the largest values
|
36
|
+
value.each_with_index do |item,i|
|
37
|
+
opts = {:id => "item#{i+1}"}
|
38
|
+
label= parent.modelgroup.zenduniq[i]
|
39
|
+
string = "(" + key + "-" + label + ")"
|
40
|
+
|
41
|
+
# Adding tool tips
|
42
|
+
if parent.get_global_option(:auto_tooltips,false)
|
43
|
+
opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
|
44
|
+
opts.store(:gerbiltooltip1, string)
|
45
|
+
opts.store(:gerbiltooltip2, "Volume #{GerbilCharts::Models::Presets.new.format_suffix(item)}")
|
46
|
+
end
|
47
|
+
|
48
|
+
# Calculating radius
|
49
|
+
radius1 = 20
|
50
|
+
effective_radius = (((item.to_f)/parent.modelgroup.sort[0].to_f).to_f * radius1)
|
51
|
+
effective_radius = [effective_radius,5.0].max
|
52
|
+
|
53
|
+
# draw out
|
54
|
+
cx = center_x + (Math.cos((Math::PI/180)*(angle+tot_angle))*(radius_x))
|
55
|
+
cy = center_y + (Math.sin((Math::PI/180)*(angle+tot_angle))*(radius_y))
|
56
|
+
g.addshape(GerbilCharts::SVGDC::SVGCircle.new(cx,cy,effective_radius),opts)
|
57
|
+
g.textout(cx-30,cy-15,label,:class => 'elementlabel')
|
58
|
+
|
59
|
+
tot_angle += angle
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|