gruff 0.0.7 → 0.0.8
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/CHANGELOG +7 -0
- data/assets/pc306715.jpg +0 -0
- data/lib/gruff.rb +3 -0
- data/lib/gruff/bar.rb +3 -0
- data/lib/gruff/base.rb +42 -18
- data/lib/gruff/line.rb +16 -4
- data/lib/gruff/photo_bar.rb +92 -0
- data/lib/gruff/side_stacked_bar.rb +119 -0
- data/lib/gruff/stacked_bar.rb +2 -1
- data/rakefile +5 -0
- data/test/area_test.rb +29 -1
- data/test/bar_test.rb +38 -19
- data/test/line_test.rb +90 -8
- data/test/photo_test.rb +44 -0
- data/test/pie_test.rb +18 -0
- data/test/sidestacked_bar_test.rb +88 -0
- data/test/stacked_bar_test.rb +6 -19
- metadata +40 -31
- data/assets/plastik-yellow.png +0 -0
data/CHANGELOG
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
|
3
|
+
== 0.0.8
|
4
|
+
|
5
|
+
* NEW Sidestacked Bar Graphs. [Alun Eyre]
|
6
|
+
* baseline_value larger than data will now show correctly. [Mike Perham]
|
7
|
+
* hide_dots and hide_lines are now options for line graphs.
|
8
|
+
*
|
9
|
+
|
3
10
|
== 0.0.6
|
4
11
|
|
5
12
|
* Fixed hang when no data is passed.
|
data/assets/pc306715.jpg
ADDED
Binary file
|
data/lib/gruff.rb
CHANGED
@@ -8,3 +8,6 @@ require File.dirname(__FILE__) + '/gruff/bar'
|
|
8
8
|
require File.dirname(__FILE__) + '/gruff/line'
|
9
9
|
require File.dirname(__FILE__) + '/gruff/pie'
|
10
10
|
require File.dirname(__FILE__) + '/gruff/stacked_bar'
|
11
|
+
require File.dirname(__FILE__) + '/gruff/side_stacked_bar'
|
12
|
+
require File.dirname(__FILE__) + '/gruff/photo_bar'
|
13
|
+
|
data/lib/gruff/bar.rb
CHANGED
@@ -20,6 +20,9 @@ class Gruff::Bar < Gruff::Base
|
|
20
20
|
@d = @d.fill current_color
|
21
21
|
|
22
22
|
data_row[1].each_with_index do |data_point, point_index|
|
23
|
+
# TODO Try this out
|
24
|
+
##data_point = 0 if data_point.nil?
|
25
|
+
|
23
26
|
# Use incremented x and scaled y
|
24
27
|
left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index)))
|
25
28
|
left_y = @graph_top + (@graph_height - data_point * @graph_height) + 1
|
data/lib/gruff/base.rb
CHANGED
@@ -3,9 +3,13 @@
|
|
3
3
|
#
|
4
4
|
# Author:: Geoffrey Grosenbach boss@topfunky.com
|
5
5
|
#
|
6
|
-
# Date:: October 23, 2005
|
6
|
+
# Date Created:: October 23, 2005
|
7
7
|
#
|
8
8
|
#
|
9
|
+
# Other contributors:
|
10
|
+
#
|
11
|
+
# Jarkko Laine, Mike Perham, Andreas Schwarz, Alun Eyre, Guillaume Theoret, and others.
|
12
|
+
#
|
9
13
|
|
10
14
|
require 'RMagick'
|
11
15
|
|
@@ -13,7 +17,7 @@ require 'yaml'
|
|
13
17
|
|
14
18
|
module Gruff
|
15
19
|
|
16
|
-
VERSION = '0.0.
|
20
|
+
VERSION = '0.0.8'
|
17
21
|
|
18
22
|
class Base
|
19
23
|
|
@@ -33,20 +37,28 @@ module Gruff
|
|
33
37
|
# RMagick must be built with the Freetype libraries for this to work properly.
|
34
38
|
attr_accessor :font
|
35
39
|
|
40
|
+
attr_accessor :hide_line_markers, :hide_legend, :hide_title
|
41
|
+
|
36
42
|
# Graph is drawn at 4/3 ratio (800x600, 400x300, etc.).
|
37
43
|
#
|
38
44
|
# Looks for Bitstream Vera as the default font. Expects an environment var of MAGICK_FONT_PATH to be set.
|
39
45
|
# (Uses RMagick's default font otherwise.)
|
40
46
|
def initialize(target_width=800)
|
41
|
-
|
42
|
-
|
47
|
+
|
48
|
+
if not Numeric === target_width
|
49
|
+
geometric_width, geometric_height = target_width.split('x')
|
50
|
+
@columns = geometric_width.to_f
|
51
|
+
@rows = geometric_height.to_f
|
52
|
+
else
|
53
|
+
@columns = target_width.to_f
|
54
|
+
@rows = target_width.to_f * 0.75
|
55
|
+
end
|
43
56
|
|
44
57
|
# Internal for calculations
|
45
58
|
@font = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
|
46
59
|
@marker_pointsize = 21.0
|
47
60
|
@raw_columns = 800.0
|
48
|
-
@raw_rows =
|
49
|
-
@graph_width = 590.0
|
61
|
+
@raw_rows = 800.0 * (@rows/@columns)
|
50
62
|
@column_count = 0
|
51
63
|
@maximum_value = 0
|
52
64
|
@has_data = false
|
@@ -55,9 +67,7 @@ module Gruff
|
|
55
67
|
@labels_seen = Hash.new
|
56
68
|
@scale = @columns / @raw_columns
|
57
69
|
|
58
|
-
@
|
59
|
-
@show_legend = true
|
60
|
-
@show_title = true
|
70
|
+
@hide_line_markers = @hide_legend = @hide_title = false
|
61
71
|
|
62
72
|
reset_themes()
|
63
73
|
theme_keynote()
|
@@ -245,16 +255,28 @@ protected
|
|
245
255
|
end
|
246
256
|
|
247
257
|
def setup_graph_measurements
|
248
|
-
|
249
|
-
|
258
|
+
# TODO Separate horizontal lines from line number labels so they can be shown or hidden independently
|
259
|
+
# TODO Get width of longest left-hand vertical text label and space left margin accordingly
|
260
|
+
unless @hide_line_markers
|
261
|
+
@graph_left = 130.0 # TODO Calculate based on string width of labels
|
262
|
+
@graph_right_margin = 80.0 # TODO see previous line
|
263
|
+
@graph_bottom_margin = 80.0
|
264
|
+
else
|
265
|
+
@graph_left = @graph_right_margin = @graph_bottom_margin = 40
|
266
|
+
end
|
267
|
+
|
268
|
+
@graph_right = @raw_columns - @graph_right_margin
|
269
|
+
|
270
|
+
@graph_width = @raw_columns - @graph_left - @graph_right_margin
|
271
|
+
|
250
272
|
@graph_top = 150.0
|
251
|
-
@graph_bottom = @raw_rows -
|
273
|
+
@graph_bottom = @raw_rows - @graph_bottom_margin
|
252
274
|
@graph_height = @graph_bottom - @graph_top
|
253
275
|
end
|
254
276
|
|
255
277
|
# Draws horizontal background lines and labels
|
256
278
|
def draw_line_markers
|
257
|
-
return
|
279
|
+
return if @hide_line_markers
|
258
280
|
|
259
281
|
# Draw horizontal line markers and annotate with numbers
|
260
282
|
@d = @d.stroke(@marker_color)
|
@@ -285,7 +307,7 @@ protected
|
|
285
307
|
|
286
308
|
# Draws a legend with the names of the datasets matched to the colors used to draw them.
|
287
309
|
def draw_legend
|
288
|
-
return
|
310
|
+
return if @hide_legend
|
289
311
|
|
290
312
|
# Sort norm_data with avg largest values set first (for display)
|
291
313
|
sort_norm_data()
|
@@ -337,7 +359,7 @@ protected
|
|
337
359
|
end
|
338
360
|
|
339
361
|
def draw_title
|
340
|
-
return
|
362
|
+
return if (@hide_title || @title.nil?)
|
341
363
|
|
342
364
|
@d.fill = @marker_color
|
343
365
|
@d.font = @font
|
@@ -354,6 +376,8 @@ protected
|
|
354
376
|
##
|
355
377
|
# Draws column labels below graph, centered over x_offset
|
356
378
|
def draw_label(x_offset, index)
|
379
|
+
return unless @show_line_markers
|
380
|
+
|
357
381
|
if !@labels[index].nil? && @labels_seen[index].nil?
|
358
382
|
@d.fill = @marker_color
|
359
383
|
@d.font = @font
|
@@ -363,7 +387,7 @@ protected
|
|
363
387
|
@d.gravity = CenterGravity
|
364
388
|
@d = @d.annotate_scaled(@base_image,
|
365
389
|
1, 1,
|
366
|
-
x_offset, @raw_rows -
|
390
|
+
x_offset, @raw_rows - (@graph_bottom_margin - 30),
|
367
391
|
@labels[index], @scale)
|
368
392
|
@labels_seen[index] = 1
|
369
393
|
end
|
@@ -392,7 +416,7 @@ protected
|
|
392
416
|
def render_image_background(image_path)
|
393
417
|
image = Image.read(image_path)
|
394
418
|
if @scale != 1.0
|
395
|
-
image[0].resize!(@scale)
|
419
|
+
image[0].resize!(@scale) # TODO Resize with new scale (crop if necessary for wide graph)
|
396
420
|
end
|
397
421
|
image[0]
|
398
422
|
end
|
@@ -441,7 +465,7 @@ protected
|
|
441
465
|
end
|
442
466
|
|
443
467
|
|
444
|
-
#
|
468
|
+
# Round down to significant digits
|
445
469
|
def significant(inc)
|
446
470
|
factor = 1.0
|
447
471
|
while (inc < 10)
|
data/lib/gruff/line.rb
CHANGED
@@ -8,6 +8,8 @@ class Gruff::Line < Gruff::Base
|
|
8
8
|
|
9
9
|
# Color of the baseline
|
10
10
|
attr_accessor :baseline_color
|
11
|
+
|
12
|
+
attr_accessor :hide_dots, :hide_lines
|
11
13
|
|
12
14
|
#
|
13
15
|
# Call with target pixel width of graph (800, 400, 300), and/or 'false' to omit lines (points only).
|
@@ -17,14 +19,18 @@ class Gruff::Line < Gruff::Base
|
|
17
19
|
# g = Gruff::Line.new(400, false) # 400px wide, no lines
|
18
20
|
#
|
19
21
|
# g = Gruff::Line.new(false) # Defaults to 800px wide, no lines
|
22
|
+
#
|
23
|
+
# TODO Remove and go back to normal. Call hide_dots or hide_lines instead
|
20
24
|
def initialize(*args)
|
21
25
|
raise ArgumentError, "Wrong number of arguments" if args.length > 2
|
22
|
-
if args.empty? or not Numeric === args.first then
|
26
|
+
if args.empty? or ((not Numeric === args.first) && (not String === args.first)) then
|
23
27
|
super()
|
24
28
|
else
|
25
29
|
super args.shift
|
26
30
|
end
|
27
|
-
|
31
|
+
|
32
|
+
@hide_dots = false
|
33
|
+
@hide_lines = args.empty? ? false : !args.shift # For backwards compatibility. Use g.hide_lines = true from now on.
|
28
34
|
@baseline_color = 'red'
|
29
35
|
end
|
30
36
|
|
@@ -63,10 +69,10 @@ class Gruff::Line < Gruff::Base
|
|
63
69
|
|
64
70
|
new_y = @graph_top + (@graph_height - data_point * @graph_height)
|
65
71
|
|
66
|
-
if
|
72
|
+
if !@hide_lines and prev_x > 0 and prev_y > 0 then
|
67
73
|
@d = @d.line(prev_x, prev_y, new_x, new_y)
|
68
74
|
end
|
69
|
-
@d = @d.circle(new_x, new_y, new_x - circle_radius, new_y)
|
75
|
+
@d = @d.circle(new_x, new_y, new_x - circle_radius, new_y) unless @hide_dots
|
70
76
|
|
71
77
|
prev_x = new_x
|
72
78
|
prev_y = new_y
|
@@ -79,7 +85,13 @@ class Gruff::Line < Gruff::Base
|
|
79
85
|
end
|
80
86
|
|
81
87
|
def normalize
|
88
|
+
@maximum_value = max(@maximum_value.to_f, @baseline_value.to_f)
|
82
89
|
super
|
83
90
|
@norm_baseline = (@baseline_value.to_f / @maximum_value.to_f) if @baseline_value
|
84
91
|
end
|
92
|
+
|
93
|
+
def max(a, b)
|
94
|
+
(a < b ? b : a)
|
95
|
+
end
|
96
|
+
|
85
97
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
class Gruff::PhotoBar < Gruff::Base
|
4
|
+
|
5
|
+
# TODO
|
6
|
+
#
|
7
|
+
# define base and cap in yml
|
8
|
+
# allow for image directory to be located elsewhere
|
9
|
+
# more exact measurements for bar heights (go all the way to the bottom of the graph)
|
10
|
+
# option to tile images instead of use a single image
|
11
|
+
# drop base label a few px lower so photo bar graphs can have a base dropping over the lower marker line
|
12
|
+
#
|
13
|
+
|
14
|
+
# The name of a pre-packaged photo-based theme.
|
15
|
+
attr_accessor :theme
|
16
|
+
|
17
|
+
def draw
|
18
|
+
super
|
19
|
+
|
20
|
+
return unless @has_data
|
21
|
+
|
22
|
+
# TODO init_photo_bar_graphics() inside an overriden draw_legend()
|
23
|
+
init_photo_bar_graphics()
|
24
|
+
|
25
|
+
#Draw#define_clip_path()
|
26
|
+
#Draw#clip_path(pathname)
|
27
|
+
#Draw#composite....with bar graph image OverCompositeOp
|
28
|
+
#
|
29
|
+
# See also
|
30
|
+
#
|
31
|
+
# Draw.pattern # define an image to tile as the filling of a draw object
|
32
|
+
#
|
33
|
+
|
34
|
+
# Setup spacing.
|
35
|
+
#
|
36
|
+
# Columns sit side-by-side.
|
37
|
+
spacing_factor = 0.9
|
38
|
+
@bar_width = current_color.columns
|
39
|
+
|
40
|
+
@norm_data.each_with_index do |data_row, row_index|
|
41
|
+
|
42
|
+
data_row[1].each_with_index do |data_point, point_index|
|
43
|
+
data_point = 0 if data_point.nil?
|
44
|
+
# Use incremented x and scaled y
|
45
|
+
left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index)))
|
46
|
+
left_y = @graph_top + (@graph_height - data_point * @graph_height) + 1
|
47
|
+
right_x = left_x + @bar_width * spacing_factor
|
48
|
+
right_y = @graph_top + @graph_height - 1
|
49
|
+
|
50
|
+
bar_image_width = current_color.columns
|
51
|
+
bar_image_height = right_y.to_f - left_y.to_f
|
52
|
+
|
53
|
+
# Crop to scale for data
|
54
|
+
bar_image = current_color.crop(0, 0, bar_image_width, bar_image_height)
|
55
|
+
|
56
|
+
@d.gravity = NorthWestGravity
|
57
|
+
@d = @d.composite(left_x, left_y, bar_image_width, bar_image_height, bar_image)
|
58
|
+
|
59
|
+
# Calculate center based on bar_width and current row
|
60
|
+
label_center = @graph_left + (@data.length * @bar_width * point_index) + (@data.length * @bar_width / 2.0)
|
61
|
+
draw_label(label_center, point_index)
|
62
|
+
end
|
63
|
+
|
64
|
+
increment_color()
|
65
|
+
end
|
66
|
+
|
67
|
+
@d.draw(@base_image)
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
# Return the chosen theme or the default
|
72
|
+
def theme
|
73
|
+
@theme || 'plastik'
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
# Sets up colors with a list of images that will be used.
|
79
|
+
# Images should be 340px tall
|
80
|
+
def init_photo_bar_graphics
|
81
|
+
color_list = Array.new
|
82
|
+
theme_dir = File.dirname(__FILE__) + '/../../assets/' + theme
|
83
|
+
|
84
|
+
Dir.open(theme_dir).each do |file|
|
85
|
+
next unless /\.png$/.match(file)
|
86
|
+
color_list << Image.read("#{theme_dir}/#{file}").first
|
87
|
+
end
|
88
|
+
@colors = color_list
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# new gruff graph type added to enable sideways stacking bar charts (basically looks like a x/y
|
2
|
+
# flip of a standard stacking bar chart)
|
3
|
+
#
|
4
|
+
# alun.eyre@googlemail.com
|
5
|
+
#
|
6
|
+
require File.dirname(__FILE__) + '/base'
|
7
|
+
|
8
|
+
class Gruff::SideStackedBar < Gruff::Base
|
9
|
+
|
10
|
+
# instead of base class version, draws vertical background lines and label
|
11
|
+
def draw_line_markers
|
12
|
+
|
13
|
+
return unless @show_line_markers
|
14
|
+
|
15
|
+
# Draw horizontal line markers and annotate with numbers
|
16
|
+
@d = @d.stroke(@marker_color)
|
17
|
+
@d = @d.stroke_width 1
|
18
|
+
number_of_lines = 5
|
19
|
+
|
20
|
+
# TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
|
21
|
+
increment = significant(@maximum_value.to_f / number_of_lines)
|
22
|
+
(0..number_of_lines).each do |index|
|
23
|
+
|
24
|
+
line_diff = (@graph_right - @graph_left) / number_of_lines
|
25
|
+
x = @graph_right - (line_diff * index) - 1
|
26
|
+
@d = @d.line(x, @graph_bottom, x, @graph_top)
|
27
|
+
|
28
|
+
diff = index - number_of_lines
|
29
|
+
marker_label = diff.abs * increment
|
30
|
+
|
31
|
+
@d.fill = @marker_color
|
32
|
+
@d.font = @font
|
33
|
+
@d.stroke = 'transparent'
|
34
|
+
@d.pointsize = scale_fontsize(@marker_pointsize)
|
35
|
+
# @d.gravity = NorthGravity
|
36
|
+
@d = @d.annotate_scaled( @base_image,
|
37
|
+
100, 20,
|
38
|
+
x - (@marker_pointsize/1.5), @graph_bottom + 40,
|
39
|
+
marker_label.to_s, @scale)
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# instead of base class version, modified to enable us to draw on the Y axis instead of X
|
45
|
+
def draw_label(y_offset, index)
|
46
|
+
if !@labels[index].nil? && @labels_seen[index].nil?
|
47
|
+
@d.fill = @marker_color
|
48
|
+
@d.font = @font
|
49
|
+
@d.stroke = 'transparent'
|
50
|
+
@d.font_weight = NormalWeight
|
51
|
+
@d.pointsize = scale_fontsize(@marker_pointsize)
|
52
|
+
@d.gravity = CenterGravity
|
53
|
+
@d = @d.annotate_scaled(@base_image,
|
54
|
+
1, 1,
|
55
|
+
@graph_left / 2, y_offset,
|
56
|
+
@labels[index], @scale)
|
57
|
+
@labels_seen[index] = 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def draw
|
62
|
+
super
|
63
|
+
|
64
|
+
return unless @has_data
|
65
|
+
|
66
|
+
# Setup spacing.
|
67
|
+
#
|
68
|
+
# Columns sit stacked.
|
69
|
+
spacing_factor = 0.9
|
70
|
+
|
71
|
+
@bar_width = @graph_height / @column_count.to_f
|
72
|
+
@d = @d.stroke_opacity 0.0
|
73
|
+
height = Array.new(@column_count, 0)
|
74
|
+
length = Array.new(@column_count, @graph_left)
|
75
|
+
|
76
|
+
@norm_data.each_with_index do |data_row, row_index|
|
77
|
+
@d = @d.fill current_color
|
78
|
+
|
79
|
+
data_row[1].each_with_index do |data_point, point_index|
|
80
|
+
|
81
|
+
## using the original calcs from the stacked bar chart to get the difference between
|
82
|
+
## part of the bart chart we wish to stack.
|
83
|
+
temp1 = @graph_left + (@graph_width -
|
84
|
+
data_point * @graph_width -
|
85
|
+
height[point_index]) + 1
|
86
|
+
temp2 = @graph_left + @graph_width - height[point_index] - 1
|
87
|
+
difference = temp2 - temp1
|
88
|
+
|
89
|
+
left_x = length[point_index] #+ 1
|
90
|
+
left_y = @graph_top + (@bar_width * point_index)
|
91
|
+
right_x = left_x + difference
|
92
|
+
right_y = left_y + @bar_width * spacing_factor
|
93
|
+
length[point_index] += difference
|
94
|
+
height[point_index] += (data_point * @graph_width - 2)
|
95
|
+
|
96
|
+
@d = @d.rectangle(left_x, left_y, right_x, right_y)
|
97
|
+
|
98
|
+
# Calculate center based on bar_width and current row
|
99
|
+
label_center = @graph_top + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0)
|
100
|
+
draw_label(label_center, point_index)
|
101
|
+
end
|
102
|
+
|
103
|
+
increment_color()
|
104
|
+
end
|
105
|
+
|
106
|
+
@d.draw(@base_image)
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
def larger_than_max?(data_point, index=0)
|
112
|
+
max(data_point, index) > @maximum_value
|
113
|
+
end
|
114
|
+
|
115
|
+
def max(data_point, index)
|
116
|
+
@data.inject(0) {|sum, item| sum + item[1][index]}
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
data/lib/gruff/stacked_bar.rb
CHANGED
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/base'
|
|
3
3
|
|
4
4
|
class Gruff::StackedBar < Gruff::Base
|
5
5
|
|
6
|
+
# Draws a bar graph, but multiple sets are stacked on top of each other.
|
6
7
|
def draw
|
7
8
|
super
|
8
9
|
|
@@ -46,7 +47,7 @@ class Gruff::StackedBar < Gruff::Base
|
|
46
47
|
@d.draw(@base_image)
|
47
48
|
end
|
48
49
|
|
49
|
-
|
50
|
+
protected
|
50
51
|
|
51
52
|
def larger_than_max?(data_point, index=0)
|
52
53
|
max(data_point, index) > @maximum_value
|
data/rakefile
CHANGED
@@ -21,6 +21,11 @@ RUBY_FORGE_USER = "topfunky"
|
|
21
21
|
desc "Default Task"
|
22
22
|
task :default => [ :test ]
|
23
23
|
|
24
|
+
desc "Clean images generated by tests"
|
25
|
+
task :clean do
|
26
|
+
rm FileList['test/output/*.png']
|
27
|
+
end
|
28
|
+
|
24
29
|
# Run the unit tests
|
25
30
|
Rake::TestTask.new { |t|
|
26
31
|
t.libs << "test"
|
data/test/area_test.rb
CHANGED
@@ -17,6 +17,17 @@ class TestGruffArea < Test::Unit::TestCase
|
|
17
17
|
[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
|
18
18
|
["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
|
19
19
|
]
|
20
|
+
@sample_labels = {
|
21
|
+
0 => '5/6',
|
22
|
+
1 => '5/15',
|
23
|
+
2 => '5/24',
|
24
|
+
3 => '5/30',
|
25
|
+
4 => '6/4',
|
26
|
+
5 => '6/12',
|
27
|
+
6 => '6/21',
|
28
|
+
7 => '6/28',
|
29
|
+
}
|
30
|
+
|
20
31
|
end
|
21
32
|
|
22
33
|
def test_area_graph
|
@@ -105,6 +116,23 @@ class TestGruffArea < Test::Unit::TestCase
|
|
105
116
|
# Default theme
|
106
117
|
g.write("test/output/area_tiny.png")
|
107
118
|
end
|
119
|
+
|
120
|
+
def test_wide
|
121
|
+
g = setup_basic_graph('800x400')
|
122
|
+
g.title = "Area Wide"
|
123
|
+
g.write("test/output/area_wide.png")
|
124
|
+
end
|
125
|
+
|
126
|
+
protected
|
127
|
+
|
128
|
+
def setup_basic_graph(size=800)
|
129
|
+
g = Gruff::Area.new(size)
|
130
|
+
g.title = "My Graph Title"
|
131
|
+
g.labels = @sample_labels
|
132
|
+
@datasets.each do |data|
|
133
|
+
g.data(data[0], data[1])
|
134
|
+
end
|
135
|
+
return g
|
136
|
+
end
|
108
137
|
|
109
138
|
end
|
110
|
-
|
data/test/bar_test.rb
CHANGED
@@ -61,23 +61,45 @@ class TestGruffBar < Test::Unit::TestCase
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_bar_image_bg
|
64
|
-
g =
|
65
|
-
g.title = "
|
66
|
-
g.labels = {
|
67
|
-
0 => '5/6',
|
68
|
-
1 => '5/15',
|
69
|
-
2 => '5/24',
|
70
|
-
3 => '5/30',
|
71
|
-
}
|
72
|
-
@datasets.each do |data|
|
73
|
-
g.data(data[0], data[1])
|
74
|
-
end
|
75
|
-
|
64
|
+
g = setup_basic_graph()
|
65
|
+
g.title = "With Image Background"
|
76
66
|
g.theme_image_based
|
77
67
|
g.write("test/output/bar_image.png")
|
78
68
|
|
79
|
-
g =
|
80
|
-
g.title = "
|
69
|
+
g = setup_basic_graph(400)
|
70
|
+
g.title = "With Image Background Small"
|
71
|
+
g.theme_image_based
|
72
|
+
g.write("test/output/bar_image_small.png")
|
73
|
+
|
74
|
+
g = setup_basic_graph('800x400')
|
75
|
+
g.title = "With Image Background Small"
|
76
|
+
g.theme_image_based
|
77
|
+
g.write("test/output/bar_image_wide.png")
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_no_line_markers
|
81
|
+
g = setup_basic_graph(400)
|
82
|
+
g.title = "No Line Markers"
|
83
|
+
g.hide_line_markers = true
|
84
|
+
g.write("test/output/bar_no_line_markers.png")
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_wide_graph
|
88
|
+
g = setup_basic_graph('800x400')
|
89
|
+
g.title = "Wide Graph"
|
90
|
+
g.write("test/output/bar_wide_graph.png")
|
91
|
+
|
92
|
+
g = setup_basic_graph('400x200')
|
93
|
+
g.title = "Wide Graph Small"
|
94
|
+
g.write("test/output/bar_wide_graph_small.png")
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
protected
|
99
|
+
|
100
|
+
def setup_basic_graph(size=800)
|
101
|
+
g = Gruff::Bar.new(size)
|
102
|
+
g.title = "My Bar Graph"
|
81
103
|
g.labels = {
|
82
104
|
0 => '5/6',
|
83
105
|
1 => '5/15',
|
@@ -87,10 +109,7 @@ class TestGruffBar < Test::Unit::TestCase
|
|
87
109
|
@datasets.each do |data|
|
88
110
|
g.data(data[0], data[1])
|
89
111
|
end
|
90
|
-
|
91
|
-
g.theme_image_based
|
92
|
-
g.write("test/output/bar_image_small.png")
|
93
|
-
|
112
|
+
g
|
94
113
|
end
|
95
114
|
|
96
115
|
|
@@ -112,6 +131,6 @@ class Gruff::Base
|
|
112
131
|
|
113
132
|
@marker_color = 'white'
|
114
133
|
|
115
|
-
@base_image = render_image_background('assets/
|
134
|
+
@base_image = render_image_background('assets/pc306715.jpg')
|
116
135
|
end
|
117
136
|
end
|
data/test/line_test.rb
CHANGED
@@ -19,6 +19,17 @@ class TestGruffLine < Test::Unit::TestCase
|
|
19
19
|
[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
|
20
20
|
["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
|
21
21
|
]
|
22
|
+
|
23
|
+
@sample_labels = {
|
24
|
+
0 => '5/6',
|
25
|
+
1 => '5/15',
|
26
|
+
2 => '5/24',
|
27
|
+
3 => '5/30',
|
28
|
+
4 => '6/4',
|
29
|
+
5 => '6/12',
|
30
|
+
6 => '6/21',
|
31
|
+
7 => '6/28',
|
32
|
+
}
|
22
33
|
end
|
23
34
|
|
24
35
|
def test_line_graph_with_themes
|
@@ -103,10 +114,10 @@ class TestGruffLine < Test::Unit::TestCase
|
|
103
114
|
def test_similar_high_end_values
|
104
115
|
g = Gruff::Line.new
|
105
116
|
g.title = "Similar High End Values Test"
|
106
|
-
g.data('similar points',
|
117
|
+
g.data('similar points', %w(29.43 29.459 29.498 29.53 29.548 29.589 29.619 29.66 29.689 29.74 29.769 29.79 29.808 29.828 29.849 29.878).collect {|i| i.to_f} )
|
107
118
|
|
108
119
|
# Default theme
|
109
|
-
g.write("test/output/
|
120
|
+
g.write("test/output/line_similar_high_end_values.png")
|
110
121
|
end
|
111
122
|
|
112
123
|
|
@@ -244,6 +255,72 @@ class TestGruffLine < Test::Unit::TestCase
|
|
244
255
|
g.write("test/output/line_some_nil_points.png")
|
245
256
|
end
|
246
257
|
|
258
|
+
def test_no_title
|
259
|
+
g = Gruff::Line.new(400)
|
260
|
+
g.labels = @sample_labels
|
261
|
+
@datasets.each do |data|
|
262
|
+
g.data(data[0], data[1])
|
263
|
+
end
|
264
|
+
|
265
|
+
g.write("test/output/line_no_title.png")
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_no_line_markers
|
269
|
+
g = setup_basic_graph(400)
|
270
|
+
g.title = "No Line Markers"
|
271
|
+
g.hide_line_markers = true
|
272
|
+
g.write("test/output/line_no_line_markers.png")
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_no_legend
|
276
|
+
g = setup_basic_graph(400)
|
277
|
+
g.title = "No Legend"
|
278
|
+
g.hide_legend = true
|
279
|
+
g.write("test/output/line_no_legend.png")
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_nothing_but_the_graph
|
283
|
+
g = setup_basic_graph(400)
|
284
|
+
g.title = "THIS TITLE SHOULD NOT DISPLAY!!!"
|
285
|
+
g.hide_line_markers = true
|
286
|
+
g.hide_legend = true
|
287
|
+
g.hide_title = true
|
288
|
+
g.write("test/output/line_nothing_but_the_graph.png")
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_baseline_larger_than_data
|
292
|
+
g = setup_basic_graph(400)
|
293
|
+
g.title = "Baseline Larger Than Data"
|
294
|
+
g.baseline_value = 150
|
295
|
+
g.write("test/output/line_large_baseline.png")
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
def test_hide_dots
|
300
|
+
g = setup_basic_graph(400)
|
301
|
+
g.title = "Hide Dots"
|
302
|
+
g.hide_dots = true
|
303
|
+
g.write("test/output/line_hide_dots.png")
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_hide_lines
|
307
|
+
g = setup_basic_graph(400)
|
308
|
+
g.title = "Hide Lines"
|
309
|
+
g.hide_lines = true
|
310
|
+
g.write("test/output/line_hide_lines.png")
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_wide_graph
|
314
|
+
g = setup_basic_graph('800x400')
|
315
|
+
g.title = "Wide Graph"
|
316
|
+
g.write("test/output/line_wide_graph.png")
|
317
|
+
|
318
|
+
g = setup_basic_graph('400x200')
|
319
|
+
g.title = "Wide Graph Small"
|
320
|
+
g.write("test/output/line_wide_graph_small.png")
|
321
|
+
end
|
322
|
+
|
323
|
+
|
247
324
|
protected
|
248
325
|
|
249
326
|
def line_graph_with_themes(size=nil)
|
@@ -254,12 +331,7 @@ protected
|
|
254
331
|
end
|
255
332
|
|
256
333
|
g.title = "Multi-Line Graph Test #{size}"
|
257
|
-
g.labels =
|
258
|
-
0 => '5/6',
|
259
|
-
2 => '5/15',
|
260
|
-
4 => '5/24',
|
261
|
-
6 => '5/30',
|
262
|
-
}
|
334
|
+
g.labels = @sample_labels
|
263
335
|
@datasets.each do |data|
|
264
336
|
g.data(data[0], data[1])
|
265
337
|
end
|
@@ -278,6 +350,16 @@ protected
|
|
278
350
|
g.theme_odeo
|
279
351
|
g.write("test/output/line_theme_odeo_#{size}.png")
|
280
352
|
end
|
353
|
+
|
354
|
+
def setup_basic_graph(size=800)
|
355
|
+
g = Gruff::Line.new(size)
|
356
|
+
g.title = "My Graph Title"
|
357
|
+
g.labels = @sample_labels
|
358
|
+
@datasets.each do |data|
|
359
|
+
g.data(data[0], data[1])
|
360
|
+
end
|
361
|
+
return g
|
362
|
+
end
|
281
363
|
|
282
364
|
end
|
283
365
|
|
data/test/photo_test.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
require 'gruff'
|
7
|
+
|
8
|
+
class TestGruffPhotoBar < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@datasets = [
|
12
|
+
[:Jimmy, [25, 36, 86, 39]],
|
13
|
+
[:Charles, [80, 54, 67, 54]],
|
14
|
+
# [:Charity, [0, nil, 100, 90]],
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_bar_graph
|
19
|
+
bar_graph_sized
|
20
|
+
bar_graph_sized(400)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def bar_graph_sized(size=800)
|
27
|
+
g = Gruff::PhotoBar.new(size)
|
28
|
+
g.title = "Photo Bar Graph Test #{size}px"
|
29
|
+
g.labels = {
|
30
|
+
0 => '5/6',
|
31
|
+
1 => '5/15',
|
32
|
+
2 => '5/24',
|
33
|
+
3 => '5/30',
|
34
|
+
}
|
35
|
+
@datasets.each do |data|
|
36
|
+
g.data(*data)
|
37
|
+
end
|
38
|
+
|
39
|
+
g.theme = 'plastik'
|
40
|
+
|
41
|
+
g.write("test/output/photo_plastik_#{size}.png")
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/test/pie_test.rb
CHANGED
@@ -17,6 +17,7 @@ class TestGruffPie < Test::Unit::TestCase
|
|
17
17
|
[:Philip, [90]],
|
18
18
|
["Arthur", [5]],
|
19
19
|
]
|
20
|
+
|
20
21
|
end
|
21
22
|
|
22
23
|
def test_pie_graph
|
@@ -79,5 +80,22 @@ class TestGruffPie < Test::Unit::TestCase
|
|
79
80
|
g.write("test/output/pie_tiny.png")
|
80
81
|
end
|
81
82
|
=end
|
83
|
+
|
84
|
+
def test_wide
|
85
|
+
g = setup_basic_graph('800x400')
|
86
|
+
g.title = "Wide Pie"
|
87
|
+
g.write("test/output/pie_wide.png")
|
88
|
+
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def setup_basic_graph(size=800)
|
93
|
+
g = Gruff::Pie.new(size)
|
94
|
+
g.title = "My Graph Title"
|
95
|
+
@datasets.each do |data|
|
96
|
+
g.data(data[0], data[1])
|
97
|
+
end
|
98
|
+
return g
|
99
|
+
end
|
82
100
|
|
83
101
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
4
|
+
#$:.unshift File.dirname(__FILE__) + "/fixtures/helpers"
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'gruff'
|
8
|
+
|
9
|
+
class TestGruffSideSideStackedBar < Test::Unit::TestCase
|
10
|
+
|
11
|
+
# TODO Delete old output files once when starting tests
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@datasets = [
|
15
|
+
[:Jimmy, [25, 36, 86, 39]],
|
16
|
+
[:Charles, [80, 54, 67, 54]],
|
17
|
+
[:Julie, [22, 29, 35, 38]],
|
18
|
+
#[:Jane, [95, 95, 95, 90, 85, 80, 88, 100]],
|
19
|
+
#[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
|
20
|
+
#["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
|
21
|
+
]
|
22
|
+
@sample_labels = {
|
23
|
+
0 => '5/6',
|
24
|
+
1 => '5/15',
|
25
|
+
2 => '5/24'
|
26
|
+
}
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_bar_graph
|
31
|
+
g = Gruff::SideStackedBar.new
|
32
|
+
g.title = "Visual Stacked Bar Graph Test"
|
33
|
+
g.labels = {
|
34
|
+
0 => '5/6',
|
35
|
+
1 => '5/15',
|
36
|
+
2 => '5/24',
|
37
|
+
3 => '5/30',
|
38
|
+
}
|
39
|
+
@datasets.each do |data|
|
40
|
+
g.data(data[0], data[1])
|
41
|
+
end
|
42
|
+
|
43
|
+
g.write("test/output/side_stacked_bar_keynote.png")
|
44
|
+
|
45
|
+
g.theme_rails_keynote
|
46
|
+
g.write("test/output/side_stacked_bar_rails_keynote.png")
|
47
|
+
|
48
|
+
g.theme_odeo
|
49
|
+
g.write("test/output/side_stacked_bar_odeo.png")
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def test_bar_graph_small
|
54
|
+
g = Gruff::SideStackedBar.new(400)
|
55
|
+
g.title = "Visual Stacked Bar Graph Test"
|
56
|
+
g.labels = {
|
57
|
+
0 => '5/6',
|
58
|
+
1 => '5/15',
|
59
|
+
2 => '5/24',
|
60
|
+
3 => '5/30',
|
61
|
+
}
|
62
|
+
@datasets.each do |data|
|
63
|
+
g.data(data[0], data[1])
|
64
|
+
end
|
65
|
+
|
66
|
+
g.write("test/output/side_stacked_bar_keynote_small.png")
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_wide
|
70
|
+
g = setup_basic_graph('800x400')
|
71
|
+
g.title = "Wide SSBar"
|
72
|
+
g.write("test/output/side_stacked_bar_wide.png")
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def setup_basic_graph(size=800)
|
78
|
+
g = Gruff::SideStackedBar.new(size)
|
79
|
+
g.title = "My Graph Title"
|
80
|
+
g.labels = @sample_labels
|
81
|
+
@datasets.each do |data|
|
82
|
+
g.data(data[0], data[1])
|
83
|
+
end
|
84
|
+
return g
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
data/test/stacked_bar_test.rb
CHANGED
@@ -19,6 +19,12 @@ class TestGruffStackedBar < Test::Unit::TestCase
|
|
19
19
|
#[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
|
20
20
|
#["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
|
21
21
|
]
|
22
|
+
@sample_labels = {
|
23
|
+
0 => '5/6',
|
24
|
+
1 => '5/15',
|
25
|
+
2 => '5/24'
|
26
|
+
}
|
27
|
+
|
22
28
|
end
|
23
29
|
|
24
30
|
def test_bar_graph
|
@@ -95,22 +101,3 @@ class TestGruffStackedBar < Test::Unit::TestCase
|
|
95
101
|
|
96
102
|
|
97
103
|
end
|
98
|
-
|
99
|
-
class Gruff::Base
|
100
|
-
def theme_image_based
|
101
|
-
reset_themes()
|
102
|
-
# Colors
|
103
|
-
@green = '#00ff00'
|
104
|
-
@grey = '#333333'
|
105
|
-
@orange = '#ff5d00'
|
106
|
-
@red = '#f61100'
|
107
|
-
@white = 'white'
|
108
|
-
@light_grey = '#999999'
|
109
|
-
@black = 'black'
|
110
|
-
@colors = [@green, @grey, @orange, @red, @white, @light_grey, @black]
|
111
|
-
|
112
|
-
@marker_color = 'white'
|
113
|
-
|
114
|
-
@base_image = render_image_background('assets/bubble.png')
|
115
|
-
end
|
116
|
-
end
|
metadata
CHANGED
@@ -3,11 +3,11 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: gruff
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2005-12-
|
6
|
+
version: 0.0.8
|
7
|
+
date: 2005-12-31 00:00:00 -08:00
|
8
8
|
summary: Beautiful graphs for one or multiple datasets.
|
9
9
|
require_paths:
|
10
|
-
|
10
|
+
- lib
|
11
11
|
email: boss@topfunky.com
|
12
12
|
homepage: http://www.topfunky.com
|
13
13
|
rubyforge_project: gruff
|
@@ -18,43 +18,52 @@ bindir: bin
|
|
18
18
|
has_rdoc: true
|
19
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
20
|
requirements:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
version: 0.0.0
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
25
24
|
version:
|
26
25
|
platform: ruby
|
27
26
|
signing_key:
|
28
27
|
cert_chain:
|
29
28
|
authors:
|
30
|
-
|
29
|
+
- Geoffrey Grosenbach
|
31
30
|
files:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
31
|
+
- rakefile
|
32
|
+
- README
|
33
|
+
- CHANGELOG
|
34
|
+
- MIT-LICENSE
|
35
|
+
- lib/gruff
|
36
|
+
- lib/gruff.rb
|
37
|
+
- lib/gruff/area.rb
|
38
|
+
- lib/gruff/bar.rb
|
39
|
+
- lib/gruff/base.rb
|
40
|
+
- lib/gruff/line.rb
|
41
|
+
- lib/gruff/photo_bar.rb
|
42
|
+
- lib/gruff/pie.rb
|
43
|
+
- lib/gruff/side_stacked_bar.rb
|
44
|
+
- lib/gruff/stacked_bar.rb
|
45
|
+
- assets/bubble.png
|
46
|
+
- assets/pc306715.jpg
|
47
|
+
- assets/plastik
|
48
|
+
- test/area_test.rb
|
49
|
+
- test/bar_test.rb
|
50
|
+
- test/line_test.rb
|
51
|
+
- test/output
|
52
|
+
- test/photo_test.rb
|
53
|
+
- test/pie_test.rb
|
54
|
+
- test/sidestacked_bar_test.rb
|
55
|
+
- test/stacked_bar_test.rb
|
53
56
|
test_files: []
|
57
|
+
|
54
58
|
rdoc_options: []
|
59
|
+
|
55
60
|
extra_rdoc_files: []
|
61
|
+
|
56
62
|
executables: []
|
63
|
+
|
57
64
|
extensions: []
|
65
|
+
|
58
66
|
requirements:
|
59
|
-
|
60
|
-
dependencies: []
|
67
|
+
- none
|
68
|
+
dependencies: []
|
69
|
+
|
data/assets/plastik-yellow.png
DELETED
Binary file
|