gerbilcharts 0.1.9 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.2.1 2009-09-15
2
+ * Changes
3
+ * Toolip and alpha effect javascript for PIE charts
4
+ * Accomodate wide labels on bar charts using tooltips
5
+ * Optimize pie chart layout further
6
+ * Fixes to stylesheet
7
+
1
8
  == 0.0.9 2009-09-10
2
9
  * Changes
3
10
  * PIE Charts
@@ -16,7 +16,7 @@ class RoundTimeRange < RawRange
16
16
  @rdelta,@ldelta=round_delta(raw_range.delta)
17
17
  @rmin=raw_range.rmin
18
18
  @rmax=round_max(raw_range.rmax,@rdelta)
19
- @gmhalfhour = Time.now.gmt_offset%3600
19
+ @gmhalfhour = Time.now.gmt_offset%3600
20
20
  end
21
21
 
22
22
  # provide labels
@@ -71,7 +71,7 @@ class RoundTimeRange < RawRange
71
71
  private
72
72
  # round_max (ceiling)
73
73
  def round_max(raw, interval)
74
- return 0 if interval == 0
74
+ return raw if interval == 0
75
75
  ni_secs = (raw.tv_sec+interval)/interval
76
76
  return Time.at(interval * ni_secs.to_i)
77
77
  end
@@ -1,3 +1,5 @@
1
+ .surfacepanel
2
+ {
1
3
  fill: none;
2
4
  stroke-width: 1;
3
5
  stroke: black;
@@ -14,50 +14,50 @@ class BarSurface < Surface
14
14
  @element_spacing = 25
15
15
  end
16
16
 
17
- def int_render(g)
17
+ def int_render(g)
18
+ # bail out of empty models quickly
19
+ if parent.modelgroup.empty?
20
+ g.textout(@bounds.left + @bounds.width/2, @bounds.height/2,
21
+ parent.modelgroup.empty_caption,{"text-anchor" => "middle"})
22
+ return
23
+ end
18
24
 
19
- # bail out of empty models quickly
20
- if parent.modelgroup.empty?
21
- g.textout(@bounds.left + @bounds.width/2, @bounds.height/2,
22
- parent.modelgroup.empty_caption,{"text-anchor" => "middle"})
23
- return
24
- end
25
-
26
- # see if the element spacing or width need to be adjusted to fit
27
- nmodels = parent.modelgroup.count
28
- delta = @bounds.width - (nmodels * (@element_width + @element_spacing) + @element_spacing)
29
- #p "delta = #{delta} width = #{@bounds.width}"
30
- if delta < 0
31
- delta_per_item = delta/(nmodels+1)
32
- @element_width += delta_per_item
33
- @element_spacing += delta_per_item
34
- end
35
- #p "Spacing = #{parent.anchor.element_spacing} spacing"
25
+ # see if the element spacing or width need to be adjusted to fit
26
+ nmodels = parent.modelgroup.count
27
+ delta = @bounds.width - (nmodels * (@element_width + @element_spacing) + @element_spacing)
28
+ if delta < 0
29
+ delta_per_item = delta/(nmodels+2)
30
+ @element_width += delta_per_item
31
+ @element_spacing = 2 * @element_width
32
+ end
36
33
 
37
- # atleast one model is present, chhug along
38
- range_options_y = parent.get_global_option(:scaling_y,:auto)
39
- ry = parent.modelgroup.effective_range_y(range_options_y)
40
- set_ajaxSurfaceContext(0,ry.rmax,"BAR") if parent.usesAjax?
34
+ # atleast one model is present, chhug along
35
+ range_options_y = parent.get_global_option(:scaling_y,:auto)
36
+ ry = parent.modelgroup.effective_range_y(range_options_y)
37
+ set_ajaxSurfaceContext(0,ry.rmax,"BAR") if parent.usesAjax?
41
38
 
42
- xpos = @bounds.left + @element_spacing
43
- parent.modelgroup.each_model_with_index do | mod, i|
44
-
39
+ xpos = @bounds.left + @element_spacing
40
+ parent.modelgroup.each_model_with_index do | mod, i|
45
41
  y=mod.latest_val
46
42
  ypos = scale_y y,ry
47
43
 
48
- opts = {:id => "item#{i}", :onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)"}
49
- opts.store(:href, mod.href) if mod.hasHref?
50
- opts.store(:gerbiltooltip1, mod.userlabel1) if mod.hasUserTips?
51
- opts.store(:gerbiltooltip2, mod.userlabel2) if mod.hasUserTips?
44
+ # Adding tool tips to the rectangle
45
+ opts = {:id => "item#{i}"}
46
+ if parent.get_global_option(:auto_tooltips,false)
47
+ opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
48
+ opts.store(:gerbiltooltip1, mod.name)
49
+ opts.store(:gerbiltooltip2, "Val = #{mod.latest_val}")
50
+ end
52
51
 
52
+ # draw the abr
53
53
  g.rectangle(xpos, ypos, @element_width, @bounds.bottom - ypos, opts)
54
- g.textout(xpos+@element_width/2,ypos-5,mod.latest_formatted_val,{:class => "elementlabel", "text-anchor" => "middle"})
55
- xpos += @element_spacing + @element_width
56
-
57
- end
58
-
54
+ g.textout( xpos+@element_width/2, ypos-5,
55
+ mod.latest_formatted_val,
56
+ {:class => "elementlabel", "text-anchor" => "middle"}
57
+ )
58
+ xpos += @element_spacing + @element_width
59
+ end
59
60
  end
60
-
61
61
  end
62
62
 
63
63
  end
@@ -14,7 +14,7 @@ class HorizontalAxis < Axis
14
14
 
15
15
  rx = parent.modelgroup.effective_round_range_x
16
16
  rx.each_label do |val,label|
17
- xp = scale_x val,rx
17
+ xp = scale_x val,rx
18
18
 
19
19
  # make sure edge ones are visible
20
20
  if (xp>=@bounds.right-10)
@@ -11,16 +11,20 @@ class HorizontalNameAxis < Axis
11
11
  end
12
12
 
13
13
  def int_render(g)
14
- super
15
-
16
- # p "Horiz name axis #{parent.anchor.element_spacing} spacing"
17
- xp = @bounds.left + parent.anchor.element_spacing + parent.anchor.element_width/2
18
- parent.modelgroup.each_model_with_index do |m,i|
19
- yoff=get_stagger_off(i,10)
20
- g.textout(xp, @bounds.top+15+yoff, m.name, {:class => "axislabel","text-anchor" => "middle"})
21
- xp += parent.anchor.element_width + parent.anchor.element_spacing
22
- end
23
-
14
+ super
15
+ xp = @bounds.left + parent.anchor.element_spacing + parent.anchor.element_width/2
16
+ parent.modelgroup.each_model_with_index do |m,i|
17
+ yoff=get_stagger_off(i,10)
18
+ #Adding tool tips to the text
19
+ opts = { :class => "axislabel"}
20
+ if parent.get_global_option(:auto_tooltips,false)
21
+ opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
22
+ opts.store(:gerbiltooltip1, m.name)
23
+ opts.store(:gerbiltooltip2, "Val = #{m.latest_val}")
24
+ end
25
+ g.textout(xp, @bounds.top+15+yoff, m.name[0..4], opts)
26
+ xp += parent.anchor.element_width + parent.anchor.element_spacing
27
+ end
24
28
  end
25
29
 
26
30
  end
@@ -2,6 +2,13 @@ module GerbilCharts::Surfaces
2
2
 
3
3
  # = Pie Surface
4
4
  class PieSurface < Surface
5
+
6
+ MIN_INSIDE_LABEL_ANGLE = 8 # do not draw outer label for small angles
7
+ MIN_OUTSIDE_LABEL_ANGLE = 3 # do not draw inner percentages (pie slice) for small angles
8
+ OUTER_OFFSET_X = 10 # x - distance offset from pie boundary
9
+ OUTER_OFFSET_Y = 10 # y - y offset from pie boundary
10
+ LEFT_LABEL_OFFSET = 30 # labels on the left of the PIE offset by this (90-270 deg)
11
+
5
12
  def initialize(opts={})
6
13
  super(opts)
7
14
  end
@@ -33,54 +40,67 @@ class PieSurface < Surface
33
40
  cy = @bounds.height/2
34
41
  current_pos_x = cx + radius
35
42
  current_pos_y = cy
36
-
37
-
43
+
38
44
  # draw each slice
39
45
  tot_angle =0
40
46
  parent.modelgroup.each_model_with_index do | mod, i|
41
- mod_angle = ((mod.latest_val*360).to_f)/(y_total.to_f)
42
- half_angle = tot_angle + mod_angle/2
43
- tot_angle = tot_angle + mod_angle
44
47
 
45
- new_pos_x = cx + (Math.cos((Math::PI/180)*tot_angle)*radius)
46
- new_pos_y = cy + (Math.sin((Math::PI/180)*tot_angle)*radius)
47
- label_pos_x = cx + (Math.cos((Math::PI/180)*half_angle)*radius_label)
48
- label_pos_y = cy + (Math.sin((Math::PI/180)*half_angle)*radius_label)
49
-
50
- percent_mod = (mod.latest_val*360/y_total)
51
- percent = (percent_mod*100/360)
52
- percent_pos_x = cx + ((Math.cos((Math::PI/180)*half_angle)*radius_label)*0.6)
53
- percent_pos_y = cy + ((Math.sin((Math::PI/180)*half_angle)*radius_label)*0.6)
54
-
55
- opts = {:id => "item#{i}" }
56
- g.addshape(GerbilCharts::SVGDC::SVGArc.new(cx,cy,radius,radius,
57
- current_pos_x,current_pos_y,
58
- new_pos_x,new_pos_y,mod_angle),
59
- opts)
48
+ mod_angle = ((mod.latest_val*360).to_f)/(y_total.to_f)
49
+ half_angle = tot_angle + mod_angle/2
50
+ tot_angle = tot_angle + mod_angle
51
+
52
+ new_pos_x = cx + (Math.cos((Math::PI/180)*tot_angle)*radius)
53
+ new_pos_y = cy + (Math.sin((Math::PI/180)*tot_angle)*radius)
54
+ label_pos_x = cx + (Math.cos((Math::PI/180)*half_angle)*radius_label)
55
+ label_pos_y = cy + (Math.sin((Math::PI/180)*half_angle)*radius_label)
60
56
 
61
- if(tot_angle > 270)
62
- if(label_pos_x > cx ) && (label_pos_y > cy )
63
- g.textout( label_pos_x, label_pos_y, "#{mod.latest_val}", :class => 'elementlabel' )
64
- g.textout( label_pos_x, label_pos_y+10, "#{mod.name}", :class => 'elementlabel' )
65
- else
66
- g.textout( label_pos_x+10 , label_pos_y , "#{mod.latest_val}", :class => 'elementlabel')
67
- g.textout( label_pos_x+10 , label_pos_y+10, "#{mod.name}", :class => 'elementlabel')
57
+ percent_mod = (mod.latest_val*360/y_total)
58
+ percent = (percent_mod*100/360)
59
+ percent_pos_x = cx + ((Math.cos((Math::PI/180)*half_angle)*radius_label)*0.6)
60
+ percent_pos_y = cy + ((Math.sin((Math::PI/180)*half_angle)*radius_label)*0.6)
61
+
62
+
63
+ # if tooltips enabled, user can position on pie slice
64
+ opts = {:id => "item#{i}"}
65
+ if parent.get_global_option(:auto_tooltips,false)
66
+ opts.merge!(:onmouseover => "OpacityDown(evt)", :onmouseout => "OpacityUp(evt)")
67
+ opts.store(:gerbiltooltip1, mod.name)
68
+ opts.store(:gerbiltooltip2, "Val = #{mod.latest_val}")
68
69
  end
69
-
70
- elsif(label_pos_x > cx ) && (label_pos_y > cy )
71
- g.textout( label_pos_x, label_pos_y, "#{mod.latest_val}", :class => 'elementlabel' )
72
- g.textout( label_pos_x, label_pos_y+10, "#{mod.name}", :class => 'elementlabel' )
73
- else
74
- g.textout( label_pos_x-30 , label_pos_y , "#{mod.latest_val}", :class => 'elementlabel')
75
- g.textout( label_pos_x-30 , label_pos_y+10, "#{mod.name}", :class => 'elementlabel')
76
- end
70
+
71
+ # draw the slice
72
+ g.addshape(GerbilCharts::SVGDC::SVGArc.new(cx,cy,radius,radius,
73
+ current_pos_x,current_pos_y,
74
+ new_pos_x,new_pos_y,mod_angle),
75
+ opts)
76
+
77
+ if(percent >= MIN_OUTSIDE_LABEL_ANGLE)
78
+ if(tot_angle > 270)
79
+ if(label_pos_x > cx ) && (label_pos_y > cy )
80
+ g.textout( label_pos_x, label_pos_y, "#{mod.latest_val}", :class => 'elementlabel')
81
+ g.textout(label_pos_x,label_pos_y+OUTER_OFFSET_Y, "#{mod.name}", :class => 'elementlabel' )
82
+ else
83
+ g.textout( label_pos_x+OUTER_OFFSET_X, label_pos_y, "#{mod.latest_val}", :class => 'elementlabel' )
84
+ g.textout( label_pos_x+OUTER_OFFSET_X, label_pos_y+OUTER_OFFSET_Y, "#{mod.name}", :class => 'elementlabel' )
85
+ end
86
+ elsif(label_pos_x > cx ) && (label_pos_y > cy )
87
+ g.textout( label_pos_x, label_pos_y, "#{mod.latest_val}", :class => 'elementlabel' )
88
+ g.textout( label_pos_x, label_pos_y+OUTER_OFFSET_Y, "#{mod.name}", :class => 'elementlabel' )
89
+ else
90
+ g.textout( label_pos_x-LEFT_LABEL_OFFSET, label_pos_y, "#{mod.latest_val}", :class => 'elementlabel' )
91
+ g.textout( label_pos_x-LEFT_LABEL_OFFSET, label_pos_y+OUTER_OFFSET_Y, "#{mod.name}", :class => 'elementlabel' )
92
+ end
93
+ end
94
+
77
95
 
78
- if(percent > 8)
79
- g.textout(percent_pos_x,percent_pos_y, "#{percent}%", :class => 'elementvalue')
80
- end
81
- current_pos_x = new_pos_x
82
- current_pos_y = new_pos_y
83
- end
96
+ if(percent > MIN_INSIDE_LABEL_ANGLE)
97
+ g.textout(percent_pos_x,percent_pos_y, "#{percent}%", :class => 'elementvalue')
98
+ end
99
+
100
+ current_pos_x = new_pos_x
101
+ current_pos_y = new_pos_y
102
+
103
+ end
84
104
  end
85
105
  end
86
106
  end
@@ -1,8 +1,8 @@
1
1
  module GerbilCharts
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
5
- TINY = 9
4
+ MINOR = 2
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/test/test_bar.rb ADDED
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ require 'trafgen'
4
+
5
+ # test pie chart
6
+ class TestBar < Test::Unit::TestCase
7
+
8
+
9
+ # test sales figures of 3 sales people
10
+ # show in a pie chart
11
+ def test_monthly_sales
12
+ modelgroup = GerbilCharts::Models::SimpleTimeSeriesModelGroup.new(
13
+ :title => "Sales figures",
14
+ :timeseries => (1..6).collect { |month| Time.local(2008,month) },
15
+ :models => [ ["Bruce", 1, 10, 18, 28, 80, 134],
16
+ ["Rex" , 112,22, 45, 70, 218, 309],
17
+ ["Sharmila", 112,22, 45, 70, 218, 245],
18
+ ["Wasim", 112,22, 45, 70, 218, 145],
19
+ ["Buzo" , 0, 23, 25, 40, 18, 59],
20
+ ["Vipin", 145,112, 22, 45, 18, 70],
21
+ ["label", 145,112, 22, 45, 18, 240],
22
+ ["very very very long name 9th item ", 145,112, 22, 45, 18, 45],
23
+ ["Others ", 145,112, 22, 45, 18, 15],
24
+ ["VIVEK", 145,112, 22, 45, 18, 170]
25
+ ]
26
+ )
27
+ mychart = GerbilCharts::Charts::BarChart.new( :width => 350, :height => 200,
28
+ :style => 'brushmetal.css', :auto_tooltips => true ,
29
+ :javascripts => {'javascripts/gerbil.js' => false, 'javascripts/prototype.js' => false}
30
+ )
31
+ mychart.modelgroup=modelgroup
32
+ mychart.render('/tmp/bar_monthly_sales.svg')
33
+ end
34
+ end
35
+
36
+
data/test/test_pie.rb CHANGED
@@ -20,14 +20,17 @@ class TestPie < Test::Unit::TestCase
20
20
  ["Wasim", 112,22, 45, 70, 218, 145],
21
21
  ["Buzo" , 0, 23, 25, 40, 18, 59],
22
22
  ["Vipin", 145,112, 22, 45, 18, 70],
23
- ["This is a long label", 145,112, 22, 45, 18, 245],
23
+ ["label", 145,112, 22, 45, 18, 240],
24
24
  ["9th item ", 145,112, 22, 45, 18, 45],
25
25
  ["Others ", 145,112, 22, 45, 18, 15],
26
26
  ["VIVEK", 145,112, 22, 45, 18, 170]
27
27
  ]
28
28
  )
29
29
 
30
- mychart = GerbilCharts::Charts::PieChart.new( :width => 350, :height => 200, :style => 'brushmetal.css')
30
+ mychart = GerbilCharts::Charts::PieChart.new( :width => 350, :height => 200,
31
+ :style => 'brushmetal.css', :auto_tooltips => true ,
32
+ :javascripts => {'/tmp/gerbil.js' => false, '/tmp/prototype.js' => false}
33
+ )
31
34
  mychart.modelgroup=modelgroup
32
35
  mychart.render('/tmp/pie_monthly_sales.svg')
33
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gerbilcharts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vivek Rajagopalan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-11 00:00:00 +05:30
12
+ date: 2009-09-17 00:00:00 +05:30
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -154,6 +154,7 @@ test_files:
154
154
  - test/test_noob.rb
155
155
  - test/test_pie.rb
156
156
  - test/test_render_string.rb
157
+ - test/test_bar.rb
157
158
  - test/test_models.rb
158
159
  - test/test_charts.rb
159
160
  - test/test_scaling.rb