gruff 0.0.3 → 0.0.4
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 +10 -1
- data/assets/bubble.png +0 -0
- data/lib/gruff/area.rb +51 -9
- data/lib/gruff/bar.rb +10 -30
- data/lib/gruff/base.rb +115 -23
- data/lib/gruff/line.rb +4 -22
- data/lib/gruff/pie.rb +84 -7
- data/rakefile +1 -1
- data/test/area_test.rb +110 -0
- data/test/bar_test.rb +60 -19
- data/test/line_test.rb +26 -0
- data/test/pie_test.rb +83 -0
- metadata +5 -2
data/CHANGELOG
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
|
3
|
+
== 0.0.4
|
4
|
+
|
5
|
+
* Added bar graphs
|
6
|
+
* Added area graphs
|
7
|
+
* Added pie graphs
|
8
|
+
* Added render_image_background for using images as background on a theme
|
9
|
+
* Fixed small size legend centering issue
|
10
|
+
* Added initial line marker rounding to significant digits (Christian Winkler)
|
11
|
+
* Line graphs line width is scaled with number of points being drawn (Christian Winkler)
|
12
|
+
|
3
13
|
== 0.0.3
|
4
14
|
|
5
15
|
* Added option to draw line graphs without the lines (points only), thanks to Eric Hodel
|
@@ -11,7 +21,6 @@ CHANGELOG
|
|
11
21
|
* Added bar graphs (initial functionality...will be enhanced)
|
12
22
|
* Removed rendered test output from gem
|
13
23
|
|
14
|
-
|
15
24
|
== 0.0.1
|
16
25
|
|
17
26
|
* Initial release.
|
data/assets/bubble.png
ADDED
Binary file
|
data/lib/gruff/area.rb
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
|
2
2
|
require 'gruff/base'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
class Gruff::Area < Gruff::Base
|
5
|
+
|
6
|
+
def draw
|
7
|
+
super
|
8
|
+
|
9
|
+
@x_increment = @graph_width / (@column_count - 1).to_f
|
10
|
+
@d = @d.stroke 'transparent'
|
11
|
+
|
12
|
+
@norm_data.each do |data_row|
|
13
|
+
poly_points = Array.new
|
14
|
+
prev_x = prev_y = 0.0
|
15
|
+
@d = @d.fill current_color
|
16
|
+
|
17
|
+
data_row[1].each_with_index do |data_point, index|
|
18
|
+
# Use incremented x and scaled y
|
19
|
+
new_x = @graph_left + (@x_increment * index)
|
20
|
+
new_y = @graph_top + (@graph_height - data_point * @graph_height)
|
21
|
+
|
22
|
+
if prev_x > 0 and prev_y > 0 then
|
23
|
+
poly_points << new_x
|
24
|
+
poly_points << new_y
|
25
|
+
|
26
|
+
#@d = @d.polyline(prev_x, prev_y, new_x, new_y)
|
27
|
+
else
|
28
|
+
poly_points << @graph_left
|
29
|
+
poly_points << @graph_bottom - 1
|
30
|
+
poly_points << new_x
|
31
|
+
poly_points << new_y
|
32
|
+
|
33
|
+
#@d = @d.polyline(@graph_left, @graph_bottom, new_x, new_y)
|
34
|
+
end
|
35
|
+
|
36
|
+
draw_label(new_x, index)
|
37
|
+
|
38
|
+
prev_x = new_x
|
39
|
+
prev_y = new_y
|
40
|
+
end
|
41
|
+
|
42
|
+
# Add closing points, draw polygon
|
43
|
+
poly_points << @graph_right
|
44
|
+
poly_points << @graph_bottom - 1
|
45
|
+
poly_points << @graph_left
|
46
|
+
poly_points << @graph_bottom - 1
|
47
|
+
|
48
|
+
@d = @d.polyline(*poly_points)
|
49
|
+
|
50
|
+
increment_color()
|
12
51
|
end
|
13
52
|
|
53
|
+
@d.draw(@base_image)
|
14
54
|
end
|
15
|
-
|
55
|
+
|
56
|
+
|
57
|
+
end
|
data/lib/gruff/bar.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'gruff/base'
|
3
3
|
|
4
|
-
|
5
|
-
class Bar < Base
|
4
|
+
class Gruff::Bar < Gruff::Base
|
6
5
|
|
7
6
|
def draw
|
8
7
|
super
|
@@ -10,6 +9,7 @@ module Gruff
|
|
10
9
|
# Setup spacing.
|
11
10
|
#
|
12
11
|
# Columns sit side-by-side.
|
12
|
+
spacing_factor = 0.9
|
13
13
|
@bar_width = @graph_width / (@column_count * @data.length).to_f
|
14
14
|
|
15
15
|
@d = @d.stroke_opacity 0.0
|
@@ -20,41 +20,21 @@ module Gruff
|
|
20
20
|
data_row[1].each_with_index do |data_point, point_index|
|
21
21
|
# Use incremented x and scaled y
|
22
22
|
left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index)))
|
23
|
-
left_y = @graph_top + (@graph_height - data_point * @graph_height)
|
24
|
-
right_x = left_x + @bar_width
|
23
|
+
left_y = @graph_top + (@graph_height - data_point * @graph_height) + 1
|
24
|
+
right_x = left_x + @bar_width * spacing_factor
|
25
25
|
right_y = @graph_top + @graph_height - 1
|
26
26
|
|
27
27
|
@d = @d.rectangle(left_x, left_y, right_x, right_y)
|
28
|
-
|
29
|
-
#
|
30
|
-
|
28
|
+
|
29
|
+
# Calculate center based on bar_width and current row
|
30
|
+
label_center = @graph_left + (@data.length * @bar_width * point_index) + (@data.length * @bar_width / 2.0)
|
31
|
+
draw_label(label_center, point_index)
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
increment_color()
|
34
35
|
end
|
35
36
|
|
36
37
|
@d.draw(@base_image)
|
37
38
|
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
# Draws column labels below graph, centered under entire block
|
42
|
-
def draw_label(x_offset, index)
|
43
|
-
# TODO
|
44
|
-
if !@labels[index].nil? && @labels_seen[index].nil?
|
45
|
-
@d.fill = @marker_color
|
46
|
-
@d.font = @font
|
47
|
-
@d.stroke = 'transparent'
|
48
|
-
@d.font_weight = NormalWeight
|
49
|
-
@d.pointsize = scale_fontsize(@marker_pointsize)
|
50
|
-
@d.gravity = CenterGravity
|
51
|
-
@d = @d.annotate_scaled(@base_image,
|
52
|
-
1, 1,
|
53
|
-
x_offset, @raw_rows - 80,
|
54
|
-
@labels[index], @scale)
|
55
|
-
@labels_seen[index] = 1
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
40
|
+
end
|
data/lib/gruff/base.rb
CHANGED
@@ -13,9 +13,11 @@ rescue LoadError
|
|
13
13
|
require 'RMagick' # capitalized on Windows
|
14
14
|
end
|
15
15
|
|
16
|
+
require 'yaml'
|
17
|
+
|
16
18
|
module Gruff
|
17
19
|
|
18
|
-
VERSION = '0.0.
|
20
|
+
VERSION = '0.0.4'
|
19
21
|
|
20
22
|
class Base
|
21
23
|
|
@@ -48,6 +50,7 @@ module Gruff
|
|
48
50
|
@marker_pointsize = 21.0
|
49
51
|
@raw_columns = 800.0
|
50
52
|
@raw_rows = 600.0
|
53
|
+
@graph_width = 590.0
|
51
54
|
@column_count = 0
|
52
55
|
@maximum_value = 0
|
53
56
|
@data = Array.new
|
@@ -55,6 +58,10 @@ module Gruff
|
|
55
58
|
@labels_seen = Hash.new
|
56
59
|
@scale = @columns / @raw_columns
|
57
60
|
|
61
|
+
@show_line_markers = true
|
62
|
+
@show_legend = true
|
63
|
+
@show_title = true
|
64
|
+
|
58
65
|
reset_themes()
|
59
66
|
theme_keynote()
|
60
67
|
end
|
@@ -179,7 +186,7 @@ module Gruff
|
|
179
186
|
def to_blob(fileformat='PNG')
|
180
187
|
draw()
|
181
188
|
return @base_image.to_blob do
|
182
|
-
self.format=fileformat
|
189
|
+
self.format = fileformat
|
183
190
|
end
|
184
191
|
end
|
185
192
|
|
@@ -201,6 +208,7 @@ protected
|
|
201
208
|
# - title
|
202
209
|
def setup_drawing
|
203
210
|
normalize()
|
211
|
+
setup_graph_measurements()
|
204
212
|
|
205
213
|
draw_line_markers()
|
206
214
|
draw_legend()
|
@@ -209,35 +217,44 @@ protected
|
|
209
217
|
|
210
218
|
# Make copy of data with values scaled between 0-100
|
211
219
|
def normalize
|
212
|
-
@norm_data
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
220
|
+
if @norm_data.nil?
|
221
|
+
@norm_data = Array.new
|
222
|
+
@data.each do |data_row|
|
223
|
+
norm_data_points = Array.new
|
224
|
+
data_row[1].each do |data_point|
|
225
|
+
norm_data_points << (data_point.to_f/@maximum_value.to_f)
|
226
|
+
end
|
227
|
+
@norm_data << [data_row[0], norm_data_points]
|
217
228
|
end
|
218
|
-
@norm_data << [data_row[0], norm_data_points]
|
219
229
|
end
|
220
230
|
end
|
221
231
|
|
222
|
-
|
223
|
-
def draw_line_markers
|
232
|
+
def setup_graph_measurements
|
224
233
|
@graph_left = 130.0
|
225
|
-
@graph_right = @
|
234
|
+
@graph_right = @graph_left + @graph_width
|
226
235
|
@graph_top = 150.0
|
227
236
|
@graph_bottom = @raw_rows - 110.0
|
228
237
|
@graph_height = @graph_bottom - @graph_top
|
229
|
-
|
238
|
+
end
|
239
|
+
|
240
|
+
# Draws horizontal background lines and labels
|
241
|
+
def draw_line_markers
|
242
|
+
return unless @show_line_markers
|
230
243
|
|
231
244
|
# Draw horizontal line markers and annotate with numbers
|
232
245
|
@d = @d.stroke(@marker_color)
|
233
246
|
@d = @d.stroke_width 1
|
234
|
-
|
235
|
-
|
236
|
-
|
247
|
+
number_of_lines = 4
|
248
|
+
|
249
|
+
# TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
|
250
|
+
increment = significant(@maximum_value.to_f / number_of_lines)
|
251
|
+
inc_graph = @graph_height.to_f / (@maximum_value.to_f / increment)
|
252
|
+
|
253
|
+
(0..number_of_lines).each do |index|
|
254
|
+
y = @graph_top + @graph_height - index.to_f * inc_graph
|
237
255
|
@d = @d.line(@graph_left, y, @graph_right, y)
|
238
|
-
|
239
|
-
marker_label =
|
240
|
-
marker_label = @maximum_value.to_f * (index.to_f/4.to_f) if index > 0
|
256
|
+
|
257
|
+
marker_label = index * increment
|
241
258
|
|
242
259
|
@d.fill = @marker_color
|
243
260
|
@d.font = @font
|
@@ -253,15 +270,24 @@ protected
|
|
253
270
|
|
254
271
|
# Draws a legend with the names of the datasets matched to the colors used to draw them.
|
255
272
|
def draw_legend
|
273
|
+
return unless @show_legend
|
274
|
+
|
256
275
|
@color_index = 0
|
257
|
-
@legend_labels = @
|
276
|
+
@legend_labels = @norm_data.collect {|item| item[0] }
|
258
277
|
|
278
|
+
# Sort norm_data with avg largest values set first (for display)
|
279
|
+
sort_norm_data()
|
280
|
+
|
259
281
|
legend_square_width = 20 # small square with color of this item
|
260
282
|
|
283
|
+
# May fix legend drawing problem at small sizes
|
284
|
+
@d.font = @font
|
285
|
+
@d.pointsize = 20
|
286
|
+
|
261
287
|
metrics = @d.get_type_metrics(@base_image, @legend_labels.join(''))
|
262
288
|
legend_text_width = metrics.width
|
263
|
-
legend_width = legend_text_width + @legend_labels.length *
|
264
|
-
legend_left =
|
289
|
+
legend_width = legend_text_width + (@legend_labels.length * legend_square_width * 2.7)
|
290
|
+
legend_left = (@raw_columns - legend_width) / 2
|
265
291
|
legend_increment = legend_width / @legend_labels.length.to_f
|
266
292
|
|
267
293
|
current_x_offset = legend_left
|
@@ -296,6 +322,8 @@ protected
|
|
296
322
|
end
|
297
323
|
|
298
324
|
def draw_title
|
325
|
+
return unless @show_title
|
326
|
+
|
299
327
|
@d.fill = @marker_color
|
300
328
|
@d.font = @font
|
301
329
|
@d.stroke = 'transparent'
|
@@ -308,11 +336,39 @@ protected
|
|
308
336
|
@title, @scale)
|
309
337
|
end
|
310
338
|
|
339
|
+
##
|
340
|
+
# Draws column labels below graph, centered over x_offset
|
341
|
+
def draw_label(x_offset, index)
|
342
|
+
if !@labels[index].nil? && @labels_seen[index].nil?
|
343
|
+
@d.fill = @marker_color
|
344
|
+
@d.font = @font
|
345
|
+
@d.stroke = 'transparent'
|
346
|
+
@d.font_weight = NormalWeight
|
347
|
+
@d.pointsize = scale_fontsize(@marker_pointsize)
|
348
|
+
@d.gravity = CenterGravity
|
349
|
+
@d = @d.annotate_scaled(@base_image,
|
350
|
+
1, 1,
|
351
|
+
x_offset, @raw_rows - 80,
|
352
|
+
@labels[index], @scale)
|
353
|
+
@labels_seen[index] = 1
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# Use with a theme definition method to draw a gradiated (or solid color) background.
|
311
358
|
def render_gradiated_background(top_color, bottom_color)
|
312
359
|
Image.new(@columns, @rows,
|
313
360
|
GradientFill.new(0, 0, 100, 0, top_color, bottom_color))
|
314
361
|
end
|
315
362
|
|
363
|
+
# Use with a theme to use an image (800x600 original) background.
|
364
|
+
def render_image_background(image_path)
|
365
|
+
image = Image.read(image_path)
|
366
|
+
if @scale != 1.0
|
367
|
+
image[0].resize!(@scale)
|
368
|
+
end
|
369
|
+
image[0]
|
370
|
+
end
|
371
|
+
|
316
372
|
def current_color
|
317
373
|
@colors[@color_index]
|
318
374
|
end
|
@@ -343,11 +399,47 @@ protected
|
|
343
399
|
return new_fontsize
|
344
400
|
end
|
345
401
|
|
402
|
+
def clip_value_if_greater_than(value, max_value)
|
403
|
+
(value > max_value) ? max_value : value
|
404
|
+
end
|
405
|
+
|
406
|
+
# round down to significant digits
|
407
|
+
def significant(inc)
|
408
|
+
factor = 1.0
|
409
|
+
while (inc < 10)
|
410
|
+
inc *= 10
|
411
|
+
factor /= 10
|
412
|
+
end
|
413
|
+
|
414
|
+
while (inc > 100)
|
415
|
+
inc /= 10
|
416
|
+
factor *= 10
|
417
|
+
end
|
418
|
+
|
419
|
+
res = inc.floor * factor
|
420
|
+
if (res.to_i.to_f == res)
|
421
|
+
res.to_i
|
422
|
+
else
|
423
|
+
res
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
# Sort with largest overall summed value at front of array
|
428
|
+
# so it shows up correctly in the drawn graph.
|
429
|
+
def sort_norm_data
|
430
|
+
@norm_data.sort! { |a,b| sums(b[1]) <=> sums(a[1]) }
|
431
|
+
end
|
432
|
+
|
433
|
+
def sums(data_set)
|
434
|
+
total_sum = 0
|
435
|
+
data_set.collect {|num| total_sum += num }
|
436
|
+
total_sum
|
437
|
+
end
|
438
|
+
|
346
439
|
end
|
347
440
|
|
348
441
|
class ColorlistExhaustedException < StandardError; end
|
349
|
-
|
350
|
-
|
442
|
+
|
351
443
|
end
|
352
444
|
|
353
445
|
|
data/lib/gruff/line.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
require 'gruff/base'
|
2
3
|
|
3
4
|
class Gruff::Line < Gruff::Base
|
@@ -24,11 +25,11 @@ class Gruff::Line < Gruff::Base
|
|
24
25
|
super
|
25
26
|
|
26
27
|
@x_increment = @graph_width / (@column_count - 1).to_f
|
27
|
-
circle_radius = 5.0
|
28
|
+
circle_radius = clip_value_if_greater_than(@columns / (@norm_data.first[1].size * 2.5), 5.0)
|
28
29
|
|
29
30
|
@d = @d.stroke_opacity 1.0
|
30
|
-
@d = @d.stroke_width 5.0
|
31
|
-
|
31
|
+
@d = @d.stroke_width clip_value_if_greater_than(@columns / (@norm_data.first[1].size * 4), 5.0)
|
32
|
+
|
32
33
|
@norm_data.each do |data_row|
|
33
34
|
prev_x = prev_y = 0.0
|
34
35
|
@d = @d.stroke current_color
|
@@ -56,24 +57,5 @@ class Gruff::Line < Gruff::Base
|
|
56
57
|
@d.draw(@base_image)
|
57
58
|
end
|
58
59
|
|
59
|
-
private
|
60
|
-
|
61
|
-
##
|
62
|
-
# Draws column labels below graph
|
63
|
-
def draw_label(x_offset, index)
|
64
|
-
if !@labels[index].nil? && @labels_seen[index].nil?
|
65
|
-
@d.fill = @marker_color
|
66
|
-
@d.font = @font
|
67
|
-
@d.stroke = 'transparent'
|
68
|
-
@d.font_weight = NormalWeight
|
69
|
-
@d.pointsize = scale_fontsize(@marker_pointsize)
|
70
|
-
@d.gravity = CenterGravity
|
71
|
-
@d = @d.annotate_scaled(@base_image,
|
72
|
-
1, 1,
|
73
|
-
x_offset, @raw_rows - 80,
|
74
|
-
@labels[index], @scale)
|
75
|
-
@labels_seen[index] = 1
|
76
|
-
end
|
77
|
-
end
|
78
60
|
|
79
61
|
end
|
data/lib/gruff/pie.rb
CHANGED
@@ -1,15 +1,92 @@
|
|
1
1
|
|
2
2
|
require 'gruff/base'
|
3
3
|
|
4
|
-
|
5
|
-
class Pie < Base
|
4
|
+
class Gruff::Pie < Gruff::Base
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def draw
|
7
|
+
@show_line_markers = false
|
8
|
+
|
9
|
+
super
|
10
10
|
|
11
|
-
|
11
|
+
diameter = @graph_height
|
12
|
+
radius = @graph_height / 2.0
|
13
|
+
top_x = @graph_left + (@graph_width - diameter) / 2.0
|
14
|
+
center_x = @graph_left + (@graph_width / 2.0)
|
15
|
+
center_y = @graph_top + (@graph_height / 2.0)
|
16
|
+
total_sum = sums_for_pie()
|
17
|
+
prev_degrees = 0.0
|
18
|
+
|
19
|
+
@norm_data.each do |data_row|
|
20
|
+
@d = @d.stroke current_color
|
21
|
+
@d = @d.fill 'transparent'
|
22
|
+
@d.stroke_width(200.0)
|
23
|
+
|
24
|
+
current_degrees = (data_row[1][0] / total_sum) * 360.0
|
25
|
+
#@d = @d.pie_slice(center_x, center_y, radius,
|
26
|
+
# current_percent * 100.0)
|
27
|
+
|
28
|
+
#@d = @d.arc(top_x, @graph_top,
|
29
|
+
# top_x + diameter, @graph_top + diameter,
|
30
|
+
# prev_degrees, prev_degrees + current_degrees)
|
31
|
+
radius = 100.0
|
32
|
+
@d = @d.ellipse(center_x, center_y,
|
33
|
+
radius, radius,
|
34
|
+
prev_degrees, prev_degrees + current_degrees)
|
35
|
+
|
36
|
+
|
37
|
+
prev_degrees += current_degrees
|
38
|
+
increment_color()
|
12
39
|
end
|
13
40
|
|
41
|
+
@d.draw(@base_image)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def sums_for_pie
|
47
|
+
total_sum = 0.0
|
48
|
+
@norm_data.collect {|data_row| total_sum += data_row[1][0] }
|
49
|
+
total_sum
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
class Magick::Draw
|
55
|
+
|
56
|
+
def pie_slice(center_x=0.0, center_y=0.0, radius=100.0, percent=0.0, rot_x=0.0)
|
57
|
+
# Okay, this part is as confusing as hell, so pay attention:
|
58
|
+
# This line determines the horizontal portion of the point on the circle where the X-Axis
|
59
|
+
# should end. It's caculated by taking the center of the on-image circle and adding that
|
60
|
+
# to the radius multiplied by the formula for determinig the point on a unit circle that a
|
61
|
+
# angle corresponds to. 3.6 * percent gives us that angle, but it's in degrees, so we need to
|
62
|
+
# convert, hence the muliplication by Pi over 180
|
63
|
+
arc_end_x = radius + (radius * Math.cos((3.6 * percent)*(Math::PI/180.0)))
|
64
|
+
|
65
|
+
# The same goes for here, except it's the vertical point instead of the horizontal one
|
66
|
+
arc_end_y = radius + (radius * Math.sin((3.6 * percent)*(Math::PI/180.0)))
|
67
|
+
|
68
|
+
# Because the SVG path format is seriously screwy, we need to set the large-arc-flag to 1
|
69
|
+
# if the angle of an arc is greater than 180 degrees. I have no idea why this is, but it is.
|
70
|
+
percent > 50 ? large_arc_flag = 1 : large_arc_flag = 0
|
71
|
+
|
72
|
+
# This is also confusing
|
73
|
+
# M tells us to move to an absolute point on the image.
|
74
|
+
# We're moving to the center of the pie
|
75
|
+
# h tells us to move to a relative point.
|
76
|
+
# We're moving to the right edge of the circle.
|
77
|
+
# A tells us to start an absolute elliptical arc.
|
78
|
+
# The first two values are the radii of the ellipse
|
79
|
+
# The third value is the x-axis-rotation (how to rotate the ellipse)
|
80
|
+
# The fourth value is our large-arc-flag
|
81
|
+
# The fifth is the sweep-flag
|
82
|
+
# The sixth and seventh values are the end point of the arc which we calculated previously
|
83
|
+
# More info on the SVG path string format at: http://www.w3.org/TR/SVG/paths.html
|
84
|
+
#
|
85
|
+
#path = "M#{radius + 2},#{radius + 2} h#{radius} A#{radius},#{radius} #{rot_x} #{large_arc_flag},1 #{arc_end_x},#{arc_end_y} z"
|
86
|
+
path = "M#{radius},#{radius} h#{radius} A#{radius},#{radius} #{rot_x} #{large_arc_flag},1 #{arc_end_x},#{arc_end_y} z"
|
87
|
+
puts "PATH: #{path}"
|
88
|
+
|
89
|
+
self.path(path)
|
14
90
|
end
|
15
|
-
|
91
|
+
|
92
|
+
end
|
data/rakefile
CHANGED
@@ -61,6 +61,7 @@ spec = Gem::Specification.new do |s|
|
|
61
61
|
|
62
62
|
s.files = [ "rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
|
63
63
|
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
64
|
+
s.files = s.files + Dir.glob( "assets/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
64
65
|
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) || item.include?("\.png") }
|
65
66
|
end
|
66
67
|
|
@@ -70,7 +71,6 @@ Rake::GemPackageTask.new(spec) do |p|
|
|
70
71
|
p.need_zip = true
|
71
72
|
end
|
72
73
|
|
73
|
-
|
74
74
|
desc "Publish the API documentation"
|
75
75
|
task :pgem => [:package] do
|
76
76
|
Rake::SshFilePublisher.new("boss@topfunky.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
data/test/area_test.rb
ADDED
@@ -0,0 +1,110 @@
|
|
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 TestGruffArea < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@datasets = [
|
13
|
+
[:Jimmy, [25, 36, 86, 39, 25, 31, 79, 88]],
|
14
|
+
[:Charles, [80, 54, 67, 54, 68, 70, 90, 95]],
|
15
|
+
[:Julie, [22, 29, 35, 38, 36, 40, 46, 57]],
|
16
|
+
[:Jane, [95, 95, 95, 90, 85, 80, 88, 100]],
|
17
|
+
[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
|
18
|
+
["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_area_graph
|
23
|
+
g = Gruff::Area.new
|
24
|
+
g.title = "Visual Multi-Area Graph Test"
|
25
|
+
g.labels = {
|
26
|
+
0 => '5/6',
|
27
|
+
2 => '5/15',
|
28
|
+
4 => '5/24',
|
29
|
+
6 => '5/30',
|
30
|
+
}
|
31
|
+
@datasets.each do |data|
|
32
|
+
g.data(data[0], data[1])
|
33
|
+
end
|
34
|
+
|
35
|
+
# Default theme
|
36
|
+
g.write("test/output/area_keynote.png")
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_resize
|
40
|
+
g = Gruff::Area.new(400)
|
41
|
+
g.title = "Small Size Multi-Area Graph Test"
|
42
|
+
g.labels = {
|
43
|
+
0 => '5/6',
|
44
|
+
2 => '5/15',
|
45
|
+
4 => '5/24',
|
46
|
+
6 => '5/30',
|
47
|
+
}
|
48
|
+
@datasets.each do |data|
|
49
|
+
g.data(data[0], data[1])
|
50
|
+
end
|
51
|
+
|
52
|
+
# Default theme
|
53
|
+
g.write("test/output/area_keynote_small.png")
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_many_datapoints
|
57
|
+
g = Gruff::Area.new
|
58
|
+
g.title = "Many Multi-Area Graph Test"
|
59
|
+
g.labels = {
|
60
|
+
0 => 'June',
|
61
|
+
10 => 'July',
|
62
|
+
30 => 'August',
|
63
|
+
50 => 'September',
|
64
|
+
}
|
65
|
+
g.data('many points', (0..50).collect {|i| rand(100) })
|
66
|
+
|
67
|
+
# Default theme
|
68
|
+
g.write("test/output/area_many.png")
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_many_areas_graph_small
|
72
|
+
g = Gruff::Area.new(400)
|
73
|
+
g.title = "Many Values Area Test 400px"
|
74
|
+
g.labels = {
|
75
|
+
0 => '5/6',
|
76
|
+
10 => '5/15',
|
77
|
+
20 => '5/24',
|
78
|
+
30 => '5/30',
|
79
|
+
40 => '6/4',
|
80
|
+
50 => '6/16'
|
81
|
+
}
|
82
|
+
%w{jimmy jane philip arthur julie bert}.each do |student_name|
|
83
|
+
g.data(student_name, (0..50).collect { |i| rand 100 })
|
84
|
+
end
|
85
|
+
|
86
|
+
# Default theme
|
87
|
+
g.write("test/output/area_many_areas_small.png")
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_area_graph_tiny
|
91
|
+
g = Gruff::Area.new(300)
|
92
|
+
g.title = "Area Test 300px"
|
93
|
+
g.labels = {
|
94
|
+
0 => '5/6',
|
95
|
+
10 => '5/15',
|
96
|
+
20 => '5/24',
|
97
|
+
30 => '5/30',
|
98
|
+
40 => '6/4',
|
99
|
+
50 => '6/16'
|
100
|
+
}
|
101
|
+
%w{jimmy jane philip arthur julie bert}.each do |student_name|
|
102
|
+
g.data(student_name, (0..50).collect { |i| rand 100 })
|
103
|
+
end
|
104
|
+
|
105
|
+
# Default theme
|
106
|
+
g.write("test/output/area_tiny.png")
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
data/test/bar_test.rb
CHANGED
@@ -26,19 +26,16 @@ class TestGruffBar < Test::Unit::TestCase
|
|
26
26
|
g.title = "Visual Multi-Line Bar Graph Test"
|
27
27
|
g.labels = {
|
28
28
|
0 => '5/6',
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
1 => '5/15',
|
30
|
+
2 => '5/24',
|
31
|
+
3 => '5/30',
|
32
32
|
}
|
33
33
|
@datasets.each do |data|
|
34
34
|
g.data(data[0], data[1])
|
35
35
|
end
|
36
36
|
|
37
37
|
g.write("test/output/bar_keynote.png")
|
38
|
-
|
39
|
-
g.theme_37signals
|
40
|
-
g.write("test/output/bar_37signals.png")
|
41
|
-
|
38
|
+
|
42
39
|
g.theme_rails_keynote
|
43
40
|
g.write("test/output/bar_rails_keynote.png")
|
44
41
|
|
@@ -52,25 +49,69 @@ class TestGruffBar < Test::Unit::TestCase
|
|
52
49
|
g.title = "Visual Multi-Line Bar Graph Test"
|
53
50
|
g.labels = {
|
54
51
|
0 => '5/6',
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
1 => '5/15',
|
53
|
+
2 => '5/24',
|
54
|
+
3 => '5/30',
|
58
55
|
}
|
59
56
|
@datasets.each do |data|
|
60
57
|
g.data(data[0], data[1])
|
61
58
|
end
|
62
59
|
|
63
60
|
g.write("test/output/bar_keynote_small.png")
|
64
|
-
|
65
|
-
g.theme_37signals
|
66
|
-
g.write("test/output/bar_37signals_small.png")
|
67
|
-
|
68
|
-
g.theme_rails_keynote
|
69
|
-
g.write("test/output/bar_rails_keynote_small.png")
|
70
|
-
|
71
|
-
g.theme_odeo
|
72
|
-
g.write("test/output/bar_odeo_small.png")
|
73
61
|
end
|
62
|
+
|
63
|
+
def test_bar_image_bg
|
64
|
+
g = Gruff::Bar.new
|
65
|
+
g.title = "Bar Graph With Image Background"
|
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
|
+
|
76
|
+
g.theme_image_based
|
77
|
+
g.write("test/output/bar_image.png")
|
78
|
+
|
79
|
+
g = Gruff::Bar.new(400)
|
80
|
+
g.title = "Bar Graph With Image Background Small"
|
81
|
+
g.labels = {
|
82
|
+
0 => '5/6',
|
83
|
+
1 => '5/15',
|
84
|
+
2 => '5/24',
|
85
|
+
3 => '5/30',
|
86
|
+
}
|
87
|
+
@datasets.each do |data|
|
88
|
+
g.data(data[0], data[1])
|
89
|
+
end
|
90
|
+
|
91
|
+
g.theme_image_based
|
92
|
+
g.write("test/output/bar_image_small.png")
|
93
|
+
|
94
|
+
end
|
95
|
+
|
74
96
|
|
97
|
+
end
|
98
|
+
|
99
|
+
class Gruff::Base
|
100
|
+
# A color scheme from the colors used on the 2005 Rails keynote presentation at RubyConf.
|
101
|
+
def theme_image_based
|
102
|
+
reset_themes()
|
103
|
+
# Colors
|
104
|
+
@green = '#00ff00'
|
105
|
+
@grey = '#333333'
|
106
|
+
@orange = '#ff5d00'
|
107
|
+
@red = '#f61100'
|
108
|
+
@white = 'white'
|
109
|
+
@light_grey = '#999999'
|
110
|
+
@black = 'black'
|
111
|
+
@colors = [@green, @grey, @orange, @red, @white, @light_grey, @black]
|
75
112
|
|
113
|
+
@marker_color = 'white'
|
114
|
+
|
115
|
+
@base_image = render_image_background('assets/bubble.png')
|
116
|
+
end
|
76
117
|
end
|
data/test/line_test.rb
CHANGED
@@ -60,6 +60,14 @@ class TestGruffLine < Test::Unit::TestCase
|
|
60
60
|
end
|
61
61
|
|
62
62
|
g.write("test/output/line_small.png")
|
63
|
+
|
64
|
+
g = Gruff::Line.new(400)
|
65
|
+
g.title = "Small Values Line Graph Test 400px"
|
66
|
+
@datasets.each do |data|
|
67
|
+
g.data(data[0], data[1])
|
68
|
+
end
|
69
|
+
|
70
|
+
g.write("test/output/line_small_small.png")
|
63
71
|
end
|
64
72
|
|
65
73
|
def test_line_large_values
|
@@ -205,6 +213,24 @@ class TestGruffLine < Test::Unit::TestCase
|
|
205
213
|
g.write("test/output/line_dots_small.png")
|
206
214
|
end
|
207
215
|
|
216
|
+
def test_many_lines_graph_small
|
217
|
+
g = Gruff::Line.new(400)
|
218
|
+
g.title = "Many Values Line Test 400px"
|
219
|
+
g.labels = {
|
220
|
+
0 => '5/6',
|
221
|
+
10 => '5/15',
|
222
|
+
20 => '5/24',
|
223
|
+
30 => '5/30',
|
224
|
+
40 => '6/4',
|
225
|
+
50 => '6/16'
|
226
|
+
}
|
227
|
+
%w{jimmy jane philip arthur julie bert}.each do |student_name|
|
228
|
+
g.data(student_name, (0..50).collect { |i| rand 100 })
|
229
|
+
end
|
230
|
+
|
231
|
+
# Default theme
|
232
|
+
g.write("test/output/line_many_lines_small.png")
|
233
|
+
end
|
208
234
|
|
209
235
|
def test_dots_graph_tiny
|
210
236
|
g = Gruff::Line.new(300, false)
|
data/test/pie_test.rb
ADDED
@@ -0,0 +1,83 @@
|
|
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 TestGruffPie < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@datasets = [
|
13
|
+
[:Jimmy, [25]],
|
14
|
+
[:Charles, [80]],
|
15
|
+
[:Julie, [22]],
|
16
|
+
[:Jane, [95]],
|
17
|
+
[:Philip, [90]],
|
18
|
+
["Arthur", [5]],
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_pie_graph
|
23
|
+
g = Gruff::Pie.new
|
24
|
+
g.title = "Visual Pie Graph Test"
|
25
|
+
@datasets.each do |data|
|
26
|
+
g.data(data[0], data[1])
|
27
|
+
end
|
28
|
+
|
29
|
+
# Default theme
|
30
|
+
g.write("test/output/pie_keynote.png")
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_pie_graph_small
|
34
|
+
g = Gruff::Pie.new(400)
|
35
|
+
g.title = "Visual Pie Graph Test Small"
|
36
|
+
@datasets.each do |data|
|
37
|
+
g.data(data[0], data[1])
|
38
|
+
end
|
39
|
+
|
40
|
+
# Default theme
|
41
|
+
g.write("test/output/pie_keynote_small.png")
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
=begin
|
46
|
+
def test_resize
|
47
|
+
g = Gruff::Pie.new(400)
|
48
|
+
g.title = "Small Size Multi-Pie Graph Test"
|
49
|
+
g.labels = {
|
50
|
+
0 => '5/6',
|
51
|
+
2 => '5/15',
|
52
|
+
4 => '5/24',
|
53
|
+
6 => '5/30',
|
54
|
+
}
|
55
|
+
@datasets.each do |data|
|
56
|
+
g.data(data[0], data[1])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Default theme
|
60
|
+
g.write("test/output/pie_keynote_small.png")
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_pie_graph_tiny
|
64
|
+
g = Gruff::Pie.new(300)
|
65
|
+
g.title = "Pie Test 300px"
|
66
|
+
g.labels = {
|
67
|
+
0 => '5/6',
|
68
|
+
10 => '5/15',
|
69
|
+
20 => '5/24',
|
70
|
+
30 => '5/30',
|
71
|
+
40 => '6/4',
|
72
|
+
50 => '6/16'
|
73
|
+
}
|
74
|
+
%w{jimmy jane philip arthur julie bert}.each do |student_name|
|
75
|
+
g.data(student_name, (0..50).collect { |i| rand 100 })
|
76
|
+
end
|
77
|
+
|
78
|
+
# Default theme
|
79
|
+
g.write("test/output/pie_tiny.png")
|
80
|
+
end
|
81
|
+
=end
|
82
|
+
|
83
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ 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-
|
6
|
+
version: 0.0.4
|
7
|
+
date: 2005-11-14 00:00:00 -08:00
|
8
8
|
summary: Beautiful graphs for one or multiple datasets.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -40,9 +40,12 @@ files:
|
|
40
40
|
- lib/gruff/base.rb
|
41
41
|
- lib/gruff/line.rb
|
42
42
|
- lib/gruff/pie.rb
|
43
|
+
- assets/bubble.png
|
44
|
+
- test/area_test.rb
|
43
45
|
- test/bar_test.rb
|
44
46
|
- test/line_test.rb
|
45
47
|
- test/output
|
48
|
+
- test/pie_test.rb
|
46
49
|
test_files: []
|
47
50
|
rdoc_options: []
|
48
51
|
extra_rdoc_files: []
|