topfunky-gruff 0.3.2

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.
Files changed (78) hide show
  1. data/History.txt +98 -0
  2. data/MIT-LICENSE +21 -0
  3. data/Manifest.txt +76 -0
  4. data/README.txt +40 -0
  5. data/Rakefile +54 -0
  6. data/assets/bubble.png +0 -0
  7. data/assets/city_scene/background/0000.png +0 -0
  8. data/assets/city_scene/background/0600.png +0 -0
  9. data/assets/city_scene/background/2000.png +0 -0
  10. data/assets/city_scene/clouds/cloudy.png +0 -0
  11. data/assets/city_scene/clouds/partly_cloudy.png +0 -0
  12. data/assets/city_scene/clouds/stormy.png +0 -0
  13. data/assets/city_scene/grass/default.png +0 -0
  14. data/assets/city_scene/haze/true.png +0 -0
  15. data/assets/city_scene/number_sample/1.png +0 -0
  16. data/assets/city_scene/number_sample/2.png +0 -0
  17. data/assets/city_scene/number_sample/default.png +0 -0
  18. data/assets/city_scene/sky/0000.png +0 -0
  19. data/assets/city_scene/sky/0200.png +0 -0
  20. data/assets/city_scene/sky/0400.png +0 -0
  21. data/assets/city_scene/sky/0600.png +0 -0
  22. data/assets/city_scene/sky/0800.png +0 -0
  23. data/assets/city_scene/sky/1000.png +0 -0
  24. data/assets/city_scene/sky/1200.png +0 -0
  25. data/assets/city_scene/sky/1400.png +0 -0
  26. data/assets/city_scene/sky/1500.png +0 -0
  27. data/assets/city_scene/sky/1700.png +0 -0
  28. data/assets/city_scene/sky/2000.png +0 -0
  29. data/assets/pc306715.jpg +0 -0
  30. data/assets/plastik/blue.png +0 -0
  31. data/assets/plastik/green.png +0 -0
  32. data/assets/plastik/red.png +0 -0
  33. data/init.rb +2 -0
  34. data/lib/gruff.rb +27 -0
  35. data/lib/gruff/accumulator_bar.rb +27 -0
  36. data/lib/gruff/area.rb +58 -0
  37. data/lib/gruff/bar.rb +83 -0
  38. data/lib/gruff/bar_conversion.rb +46 -0
  39. data/lib/gruff/base.rb +1073 -0
  40. data/lib/gruff/deprecated.rb +39 -0
  41. data/lib/gruff/line.rb +105 -0
  42. data/lib/gruff/mini/bar.rb +32 -0
  43. data/lib/gruff/mini/legend.rb +77 -0
  44. data/lib/gruff/mini/pie.rb +36 -0
  45. data/lib/gruff/mini/side_bar.rb +35 -0
  46. data/lib/gruff/net.rb +142 -0
  47. data/lib/gruff/photo_bar.rb +100 -0
  48. data/lib/gruff/pie.rb +124 -0
  49. data/lib/gruff/scene.rb +209 -0
  50. data/lib/gruff/side_bar.rb +114 -0
  51. data/lib/gruff/side_stacked_bar.rb +73 -0
  52. data/lib/gruff/spider.rb +130 -0
  53. data/lib/gruff/stacked_area.rb +66 -0
  54. data/lib/gruff/stacked_bar.rb +53 -0
  55. data/lib/gruff/stacked_mixin.rb +23 -0
  56. data/rails_generators/gruff/gruff_generator.rb +63 -0
  57. data/rails_generators/gruff/templates/controller.rb +32 -0
  58. data/rails_generators/gruff/templates/functional_test.rb +24 -0
  59. data/test/gruff_test_case.rb +123 -0
  60. data/test/test_accumulator_bar.rb +50 -0
  61. data/test/test_area.rb +134 -0
  62. data/test/test_bar.rb +283 -0
  63. data/test/test_base.rb +8 -0
  64. data/test/test_bullet.rb +26 -0
  65. data/test/test_legend.rb +71 -0
  66. data/test/test_line.rb +513 -0
  67. data/test/test_mini_bar.rb +32 -0
  68. data/test/test_mini_pie.rb +20 -0
  69. data/test/test_mini_side_bar.rb +37 -0
  70. data/test/test_net.rb +230 -0
  71. data/test/test_photo.rb +41 -0
  72. data/test/test_pie.rb +154 -0
  73. data/test/test_scene.rb +100 -0
  74. data/test/test_side_bar.rb +12 -0
  75. data/test/test_sidestacked_bar.rb +89 -0
  76. data/test/test_spider.rb +216 -0
  77. data/test/test_stacked_bar.rb +52 -0
  78. metadata +157 -0
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+ require File.dirname(__FILE__) + '/side_bar'
3
+ require File.dirname(__FILE__) + '/stacked_mixin'
4
+
5
+ ##
6
+ # New gruff graph type added to enable sideways stacking bar charts
7
+ # (basically looks like a x/y flip of a standard stacking bar chart)
8
+ #
9
+ # alun.eyre@googlemail.com
10
+
11
+ class Gruff::SideStackedBar < Gruff::SideBar
12
+ include StackedMixin
13
+
14
+ def draw
15
+ @has_left_labels = true
16
+ get_maximum_by_stack
17
+ super
18
+
19
+ return unless @has_data
20
+
21
+ # Setup spacing.
22
+ #
23
+ # Columns sit stacked.
24
+ spacing_factor = 0.9
25
+
26
+ @bar_width = @graph_height / @column_count.to_f
27
+ @d = @d.stroke_opacity 0.0
28
+ height = Array.new(@column_count, 0)
29
+ length = Array.new(@column_count, @graph_left)
30
+
31
+ @norm_data.each_with_index do |data_row, row_index|
32
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
33
+
34
+ data_row[1].each_with_index do |data_point, point_index|
35
+
36
+ ## using the original calcs from the stacked bar chart to get the difference between
37
+ ## part of the bart chart we wish to stack.
38
+ temp1 = @graph_left + (@graph_width -
39
+ data_point * @graph_width -
40
+ height[point_index]) + 1
41
+ temp2 = @graph_left + @graph_width - height[point_index] - 1
42
+ difference = temp2 - temp1
43
+
44
+ left_x = length[point_index] #+ 1
45
+ left_y = @graph_top + (@bar_width * point_index)
46
+ right_x = left_x + difference
47
+ right_y = left_y + @bar_width * spacing_factor
48
+ length[point_index] += difference
49
+ height[point_index] += (data_point * @graph_width - 2)
50
+
51
+ @d = @d.rectangle(left_x, left_y, right_x, right_y)
52
+
53
+ # Calculate center based on bar_width and current row
54
+ label_center = @graph_top + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0)
55
+ draw_label(label_center, point_index)
56
+ end
57
+
58
+ end
59
+
60
+ @d.draw(@base_image)
61
+ end
62
+
63
+ protected
64
+
65
+ def larger_than_max?(data_point, index=0)
66
+ max(data_point, index) > @maximum_value
67
+ end
68
+
69
+ def max(data_point, index)
70
+ @data.inject(0) {|sum, item| sum + item[1][index]}
71
+ end
72
+
73
+ end
@@ -0,0 +1,130 @@
1
+
2
+ require File.dirname(__FILE__) + '/base'
3
+
4
+ # Experimental!!! See also the Net graph.
5
+ #
6
+ # Submitted by Kevin Clark http://glu.ttono.us/
7
+ class Gruff::Spider < Gruff::Base
8
+
9
+ # Hide all text
10
+ attr_reader :hide_text
11
+ attr_accessor :hide_axes
12
+ attr_reader :transparent_background
13
+
14
+ def transparent_background=(value)
15
+ @transparent_background = value
16
+ @base_image = render_transparent_background if value
17
+ end
18
+
19
+ def hide_text=(value)
20
+ @hide_title = @hide_text = value
21
+ end
22
+
23
+ def initialize(max_value, target_width = 800)
24
+ super(target_width)
25
+ @max_value = max_value
26
+ @hide_legend = true;
27
+ end
28
+
29
+ def draw
30
+ @hide_line_markers = true
31
+
32
+ super
33
+
34
+ return unless @has_data
35
+
36
+ # Setup basic positioning
37
+ diameter = @graph_height
38
+ radius = @graph_height / 2.0
39
+ top_x = @graph_left + (@graph_width - diameter) / 2.0
40
+ center_x = @graph_left + (@graph_width / 2.0)
41
+ center_y = @graph_top + (@graph_height / 2.0) - 25 # Move graph up a bit
42
+
43
+ @unit_length = radius / @max_value
44
+
45
+
46
+ total_sum = sums_for_spider
47
+ prev_degrees = 0.0
48
+ additive_angle = (2 * Math::PI)/ @data.size
49
+
50
+ current_angle = 0.0
51
+
52
+ # Draw axes
53
+ draw_axes(center_x, center_y, radius, additive_angle) unless hide_axes
54
+
55
+ # Draw polygon
56
+ draw_polygon(center_x, center_y, additive_angle)
57
+
58
+
59
+ @d.draw(@base_image)
60
+ end
61
+
62
+ private
63
+
64
+ def normalize_points(value)
65
+ value * @unit_length
66
+ end
67
+
68
+ def draw_label(center_x, center_y, angle, radius, amount)
69
+ r_offset = 50 # The distance out from the center of the pie to get point
70
+ x_offset = center_x # The label points need to be tweaked slightly
71
+ y_offset = center_y + 0 # This one doesn't though
72
+ x = x_offset + ((radius + r_offset) * Math.cos(angle))
73
+ y = y_offset + ((radius + r_offset) * Math.sin(angle))
74
+
75
+ # Draw label
76
+ @d.fill = @marker_color
77
+ @d.font = @font if @font
78
+ @d.pointsize = scale_fontsize(legend_font_size)
79
+ @d.stroke = 'transparent'
80
+ @d.font_weight = BoldWeight
81
+ @d.gravity = CenterGravity
82
+ @d.annotate_scaled( @base_image,
83
+ 0, 0,
84
+ x, y,
85
+ amount, @scale)
86
+ end
87
+
88
+ def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
89
+ return if hide_axes
90
+
91
+ current_angle = 0.0
92
+
93
+ @data.each do |data_row|
94
+ @d.stroke(line_color || data_row[DATA_COLOR_INDEX])
95
+ @d.stroke_width 5.0
96
+
97
+ x_offset = radius * Math.cos(current_angle)
98
+ y_offset = radius * Math.sin(current_angle)
99
+
100
+ @d.line(center_x, center_y,
101
+ center_x + x_offset,
102
+ center_y + y_offset)
103
+
104
+ draw_label(center_x, center_y, current_angle, radius, data_row[0].to_s) unless hide_text
105
+
106
+ current_angle += additive_angle
107
+ end
108
+ end
109
+
110
+ def draw_polygon(center_x, center_y, additive_angle, color = nil)
111
+ points = []
112
+ current_angle = 0.0
113
+ @data.each do |data_row|
114
+ points << center_x + normalize_points(data_row[1][0]) * Math.cos(current_angle)
115
+ points << center_y + normalize_points(data_row[1][0]) * Math.sin(current_angle)
116
+ current_angle += additive_angle
117
+ end
118
+
119
+ @d.stroke_width 1.0
120
+ @d.stroke(color || @marker_color)
121
+ @d.fill(color || @marker_color)
122
+ @d.fill_opacity 0.4
123
+ @d.polygon(*points)
124
+ end
125
+
126
+ def sums_for_spider
127
+ @data.inject(0.0) {|sum, data_row| sum += data_row[1][0]}
128
+ end
129
+
130
+ end
@@ -0,0 +1,66 @@
1
+
2
+ require File.dirname(__FILE__) + '/base'
3
+ require File.dirname(__FILE__) + '/stacked_mixin'
4
+
5
+ class Gruff::StackedArea < Gruff::Base
6
+ include StackedMixin
7
+ attr_accessor :last_series_goes_on_bottom
8
+
9
+ def draw
10
+ super
11
+
12
+ return unless @has_data
13
+
14
+ @x_increment = @graph_width / (@column_count - 1).to_f
15
+ @d = @d.stroke 'transparent'
16
+
17
+ height = Array.new(@column_count, 0)
18
+
19
+ data_points = nil
20
+ iterator = last_series_goes_on_bottom ? :reverse_each : :each
21
+ @norm_data.send(iterator) do |data_row|
22
+ prev_data_points = data_points
23
+ data_points = Array.new
24
+
25
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
26
+
27
+ data_row[1].each_with_index do |data_point, index|
28
+ # Use incremented x and scaled y
29
+ new_x = @graph_left + (@x_increment * index)
30
+ new_y = @graph_top + (@graph_height - data_point * @graph_height - height[index])
31
+
32
+ height[index] += (data_point * @graph_height)
33
+
34
+ data_points << new_x
35
+ data_points << new_y
36
+
37
+ draw_label(new_x, index)
38
+
39
+ end
40
+
41
+ if prev_data_points
42
+ poly_points = data_points.dup
43
+ (prev_data_points.length/2 - 1).downto(0) do |i|
44
+ poly_points << prev_data_points[2*i]
45
+ poly_points << prev_data_points[2*i+1]
46
+ end
47
+ poly_points << data_points[0]
48
+ poly_points << data_points[1]
49
+ else
50
+ poly_points = data_points.dup
51
+ poly_points << @graph_right
52
+ poly_points << @graph_bottom - 1
53
+ poly_points << @graph_left
54
+ poly_points << @graph_bottom - 1
55
+ poly_points << data_points[0]
56
+ poly_points << data_points[1]
57
+ end
58
+ @d = @d.polyline(*poly_points)
59
+
60
+ end
61
+
62
+ @d.draw(@base_image)
63
+ end
64
+
65
+
66
+ end
@@ -0,0 +1,53 @@
1
+
2
+ require File.dirname(__FILE__) + '/base'
3
+ require File.dirname(__FILE__) + '/stacked_mixin'
4
+
5
+ class Gruff::StackedBar < Gruff::Base
6
+ include StackedMixin
7
+
8
+ # Draws a bar graph, but multiple sets are stacked on top of each other.
9
+ def draw
10
+ get_maximum_by_stack
11
+ super
12
+ return unless @has_data
13
+
14
+ # Setup spacing.
15
+ #
16
+ # Columns sit stacked.
17
+ spacing_factor = 0.9
18
+ @bar_width = @graph_width / @column_count.to_f
19
+
20
+ @d = @d.stroke_opacity 0.0
21
+
22
+ height = Array.new(@column_count, 0)
23
+
24
+ @norm_data.each_with_index do |data_row, row_index|
25
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
26
+
27
+ data_row[1].each_with_index do |data_point, point_index|
28
+ # Calculate center based on bar_width and current row
29
+ label_center = @graph_left + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0)
30
+ draw_label(label_center, point_index)
31
+
32
+ next if (data_point == 0)
33
+ # Use incremented x and scaled y
34
+ left_x = @graph_left + (@bar_width * point_index)
35
+ left_y = @graph_top + (@graph_height -
36
+ data_point * @graph_height -
37
+ height[point_index]) + 1
38
+ right_x = left_x + @bar_width * spacing_factor
39
+ right_y = @graph_top + @graph_height - height[point_index] - 1
40
+
41
+ # update the total height of the current stacked bar
42
+ height[point_index] += (data_point * @graph_height )
43
+
44
+ @d = @d.rectangle(left_x, left_y, right_x, right_y)
45
+
46
+ end
47
+
48
+ end
49
+
50
+ @d.draw(@base_image)
51
+ end
52
+
53
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Gruff::Base::StackedMixin
3
+ # Used by StackedBar and child classes.
4
+ #
5
+ # tsal: moved from Base 03 FEB 2007
6
+ DATA_VALUES_INDEX = Gruff::Base::DATA_VALUES_INDEX
7
+ def get_maximum_by_stack
8
+ # Get sum of each stack
9
+ max_hash = {}
10
+ @data.each do |data_set|
11
+ data_set[DATA_VALUES_INDEX].each_with_index do |data_point, i|
12
+ max_hash[i] = 0.0 unless max_hash[i]
13
+ max_hash[i] += data_point.to_f
14
+ end
15
+ end
16
+
17
+ # @maximum_value = 0
18
+ max_hash.keys.each do |key|
19
+ @maximum_value = max_hash[key] if max_hash[key] > @maximum_value
20
+ end
21
+ @minimum_value = 0
22
+ end
23
+ end
@@ -0,0 +1,63 @@
1
+ class GruffGenerator < Rails::Generator::NamedBase
2
+
3
+ attr_reader :controller_name,
4
+ :controller_class_path,
5
+ :controller_file_path,
6
+ :controller_class_nesting,
7
+ :controller_class_nesting_depth,
8
+ :controller_class_name,
9
+ :controller_singular_name,
10
+ :controller_plural_name,
11
+ :parent_folder_for_require
12
+ alias_method :controller_file_name, :controller_singular_name
13
+ alias_method :controller_table_name, :controller_plural_name
14
+
15
+ def initialize(runtime_args, runtime_options = {})
16
+ super
17
+
18
+ # Take controller name from the next argument.
19
+ @controller_name = runtime_args.shift
20
+
21
+ base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
22
+ @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
23
+
24
+ if @controller_class_nesting.empty?
25
+ @controller_class_name = @controller_class_name_without_nesting
26
+ else
27
+ @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
28
+ end
29
+ end
30
+
31
+ def manifest
32
+ record do |m|
33
+ # Check for class naming collisions.
34
+ m.class_collisions controller_class_path, "#{controller_class_name}Controller",
35
+ "#{controller_class_name}ControllerTest"
36
+
37
+ # Controller, helper, views, and test directories.
38
+ m.directory File.join('app/controllers', controller_class_path)
39
+ m.directory File.join('test/functional', controller_class_path)
40
+
41
+ m.template 'controller.rb',
42
+ File.join('app/controllers',
43
+ controller_class_path,
44
+ "#{controller_file_name}_controller.rb")
45
+
46
+ # For some reason this doesn't take effect if done in initialize()
47
+ @parent_folder_for_require = @controller_class_path.join('/').gsub(%r%app/controllers/?%, '')
48
+ @parent_folder_for_require += @parent_folder_for_require.blank? ? '' : '/'
49
+
50
+ m.template 'functional_test.rb',
51
+ File.join('test/functional',
52
+ controller_class_path,
53
+ "#{controller_file_name}_controller_test.rb")
54
+
55
+ end
56
+ end
57
+
58
+ protected
59
+ # Override with your own usage banner.
60
+ def banner
61
+ "Usage: #{$0} gruff ControllerName"
62
+ end
63
+ end
@@ -0,0 +1,32 @@
1
+ class <%= controller_class_name %>Controller < ApplicationController
2
+
3
+ # To make caching easier, add a line like this to config/routes.rb:
4
+ # map.graph "graph/:action/:id/image.png", :controller => "graph"
5
+ #
6
+ # Then reference it with the named route:
7
+ # image_tag graph_url(:action => 'show', :id => 42)
8
+
9
+ def show
10
+ g = Gruff::Line.new
11
+ # Uncomment to use your own theme or font
12
+ # See http://colourlovers.com or http://www.firewheeldesign.com/widgets/ for color ideas
13
+ # g.theme = {
14
+ # :colors => ['#663366', '#cccc99', '#cc6633', '#cc9966', '#99cc99'],
15
+ # :marker_color => 'white',
16
+ # :background_colors => ['black', '#333333']
17
+ # }
18
+ # g.font = File.expand_path('artwork/fonts/VeraBd.ttf', RAILS_ROOT)
19
+
20
+ g.title = "Gruff-o-Rama"
21
+
22
+ g.data("Apples", [1, 2, 3, 4, 4, 3])
23
+ g.data("Oranges", [4, 8, 7, 9, 8, 9])
24
+ g.data("Watermelon", [2, 3, 1, 5, 6, 8])
25
+ g.data("Peaches", [9, 9, 10, 8, 7, 9])
26
+
27
+ g.labels = {0 => '2004', 2 => '2005', 4 => '2006'}
28
+
29
+ send_data(g.to_blob, :disposition => 'inline', :type => 'image/png', :filename => "gruff.png")
30
+ end
31
+
32
+ end