gerbilcharts 0.2.13 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|