gerbilcharts 0.1.9 → 0.2.1

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 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