Skip to content
Browse files

Merge branch 'master' of git://github.com/topfunky/gruff

  • Loading branch information...
2 parents 479dbe7 + 5df19f4 commit ef73ab9358eba149cbdc83fd6a7f4318228b0358 @nikosd nikosd committed
View
8 History.txt
@@ -1,6 +1,12 @@
+== 0.3.6
+
+* Fixed manifest to list dot graph [theirishpenguin]
+* Fixed color cycling error [Gunnar Wolf]
+* Handle case where a line graph data set only has one value [Ron Colwill]
+
== 0.3.5
-* ???
+* Added dot graph from Erik Andrejko
== 0.3.4
View
2 Manifest.txt
@@ -39,6 +39,7 @@ lib/gruff/bar_conversion.rb
lib/gruff/base.rb
lib/gruff/bullet.rb
lib/gruff/deprecated.rb
+lib/gruff/dot.rb
lib/gruff/line.rb
lib/gruff/mini/bar.rb
lib/gruff/mini/legend.rb
@@ -63,6 +64,7 @@ test/test_area.rb
test/test_bar.rb
test/test_base.rb
test/test_bullet.rb
+test/test_dot.rb
test/test_legend.rb
test/test_line.rb
test/test_mini_bar.rb
View
16 gruff.gemspec
@@ -4,30 +4,30 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Geoffrey Grosenbach"]
- s.date = %q{2008-08-18}
+ s.date = %q{2009-01-14}
s.description = %q{Beautiful graphs for one or multiple datasets. Can be used on websites or in documents.}
s.email = %q{boss@topfunky.com}
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
- s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.txt", "Rakefile", "assets/bubble.png", "assets/city_scene/background/0000.png", "assets/city_scene/background/0600.png", "assets/city_scene/background/2000.png", "assets/city_scene/clouds/cloudy.png", "assets/city_scene/clouds/partly_cloudy.png", "assets/city_scene/clouds/stormy.png", "assets/city_scene/grass/default.png", "assets/city_scene/haze/true.png", "assets/city_scene/number_sample/1.png", "assets/city_scene/number_sample/2.png", "assets/city_scene/number_sample/default.png", "assets/city_scene/sky/0000.png", "assets/city_scene/sky/0200.png", "assets/city_scene/sky/0400.png", "assets/city_scene/sky/0600.png", "assets/city_scene/sky/0800.png", "assets/city_scene/sky/1000.png", "assets/city_scene/sky/1200.png", "assets/city_scene/sky/1400.png", "assets/city_scene/sky/1500.png", "assets/city_scene/sky/1700.png", "assets/city_scene/sky/2000.png", "assets/pc306715.jpg", "assets/plastik/blue.png", "assets/plastik/green.png", "assets/plastik/red.png", "init.rb", "lib/gruff.rb", "lib/gruff/accumulator_bar.rb", "lib/gruff/area.rb", "lib/gruff/bar.rb", "lib/gruff/bar_conversion.rb", "lib/gruff/base.rb", "lib/gruff/bullet.rb", "lib/gruff/deprecated.rb", "lib/gruff/line.rb", "lib/gruff/mini/bar.rb", "lib/gruff/mini/legend.rb", "lib/gruff/mini/pie.rb", "lib/gruff/mini/side_bar.rb", "lib/gruff/net.rb", "lib/gruff/photo_bar.rb", "lib/gruff/pie.rb", "lib/gruff/scene.rb", "lib/gruff/side_bar.rb", "lib/gruff/side_stacked_bar.rb", "lib/gruff/spider.rb", "lib/gruff/stacked_area.rb", "lib/gruff/stacked_bar.rb", "lib/gruff/stacked_mixin.rb", "rails_generators/gruff/gruff_generator.rb", "rails_generators/gruff/templates/controller.rb", "rails_generators/gruff/templates/functional_test.rb", "test/gruff_test_case.rb", "test/test_accumulator_bar.rb", "test/test_area.rb", "test/test_bar.rb", "test/test_base.rb", "test/test_bullet.rb", "test/test_legend.rb", "test/test_line.rb", "test/test_mini_bar.rb", "test/test_mini_pie.rb", "test/test_mini_side_bar.rb", "test/test_net.rb", "test/test_photo.rb", "test/test_pie.rb", "test/test_scene.rb", "test/test_side_bar.rb", "test/test_sidestacked_bar.rb", "test/test_spider.rb", "test/test_stacked_area.rb", "test/test_stacked_bar.rb"]
+ s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.txt", "Rakefile", "assets/bubble.png", "assets/city_scene/background/0000.png", "assets/city_scene/background/0600.png", "assets/city_scene/background/2000.png", "assets/city_scene/clouds/cloudy.png", "assets/city_scene/clouds/partly_cloudy.png", "assets/city_scene/clouds/stormy.png", "assets/city_scene/grass/default.png", "assets/city_scene/haze/true.png", "assets/city_scene/number_sample/1.png", "assets/city_scene/number_sample/2.png", "assets/city_scene/number_sample/default.png", "assets/city_scene/sky/0000.png", "assets/city_scene/sky/0200.png", "assets/city_scene/sky/0400.png", "assets/city_scene/sky/0600.png", "assets/city_scene/sky/0800.png", "assets/city_scene/sky/1000.png", "assets/city_scene/sky/1200.png", "assets/city_scene/sky/1400.png", "assets/city_scene/sky/1500.png", "assets/city_scene/sky/1700.png", "assets/city_scene/sky/2000.png", "assets/pc306715.jpg", "assets/plastik/blue.png", "assets/plastik/green.png", "assets/plastik/red.png", "init.rb", "lib/gruff.rb", "lib/gruff/accumulator_bar.rb", "lib/gruff/area.rb", "lib/gruff/bar.rb", "lib/gruff/bar_conversion.rb", "lib/gruff/base.rb", "lib/gruff/bullet.rb", "lib/gruff/deprecated.rb", "lib/gruff/dot.rb", "lib/gruff/line.rb", "lib/gruff/mini/bar.rb", "lib/gruff/mini/legend.rb", "lib/gruff/mini/pie.rb", "lib/gruff/mini/side_bar.rb", "lib/gruff/net.rb", "lib/gruff/photo_bar.rb", "lib/gruff/pie.rb", "lib/gruff/scene.rb", "lib/gruff/side_bar.rb", "lib/gruff/side_stacked_bar.rb", "lib/gruff/spider.rb", "lib/gruff/stacked_area.rb", "lib/gruff/stacked_bar.rb", "lib/gruff/stacked_mixin.rb", "rails_generators/gruff/gruff_generator.rb", "rails_generators/gruff/templates/controller.rb", "rails_generators/gruff/templates/functional_test.rb", "test/gruff_test_case.rb", "test/test_accumulator_bar.rb", "test/test_area.rb", "test/test_bar.rb", "test/test_base.rb", "test/test_bullet.rb", "test/test_dot.rb", "test/test_legend.rb", "test/test_line.rb", "test/test_mini_bar.rb", "test/test_mini_pie.rb", "test/test_mini_side_bar.rb", "test/test_net.rb", "test/test_photo.rb", "test/test_pie.rb", "test/test_scene.rb", "test/test_side_bar.rb", "test/test_sidestacked_bar.rb", "test/test_spider.rb", "test/test_stacked_area.rb", "test/test_stacked_bar.rb"]
s.has_rdoc = true
s.homepage = %q{http://nubyonrails.com/pages/gruff}
s.rdoc_options = ["--main", "README.txt"]
s.require_paths = ["lib"]
s.rubyforge_project = %q{gruff}
- s.rubygems_version = %q{1.2.0}
+ s.rubygems_version = %q{1.3.1}
s.summary = %q{Beautiful graphs for one or multiple datasets.}
- s.test_files = ["test/test_accumulator_bar.rb", "test/test_area.rb", "test/test_bar.rb", "test/test_base.rb", "test/test_bullet.rb", "test/test_legend.rb", "test/test_line.rb", "test/test_mini_bar.rb", "test/test_mini_pie.rb", "test/test_mini_side_bar.rb", "test/test_net.rb", "test/test_photo.rb", "test/test_pie.rb", "test/test_scene.rb", "test/test_side_bar.rb", "test/test_sidestacked_bar.rb", "test/test_spider.rb", "test/test_stacked_area.rb", "test/test_stacked_bar.rb"]
+ s.test_files = ["test/test_accumulator_bar.rb", "test/test_area.rb", "test/test_bar.rb", "test/test_base.rb", "test/test_bullet.rb", "test/test_dot.rb", "test/test_legend.rb", "test/test_line.rb", "test/test_mini_bar.rb", "test/test_mini_pie.rb", "test/test_mini_side_bar.rb", "test/test_net.rb", "test/test_photo.rb", "test/test_pie.rb", "test/test_scene.rb", "test/test_side_bar.rb", "test/test_sidestacked_bar.rb", "test/test_spider.rb", "test/test_stacked_area.rb", "test/test_stacked_bar.rb"]
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
- if current_version >= 3 then
- s.add_development_dependency(%q<hoe>, [">= 1.7.0"])
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q<hoe>, [">= 1.8.2"])
else
- s.add_dependency(%q<hoe>, [">= 1.7.0"])
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
end
else
- s.add_dependency(%q<hoe>, [">= 1.7.0"])
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
end
end
View
3 lib/gruff.rb
@@ -5,6 +5,7 @@
area
bar
line
+ dot
pie
spider
net
@@ -24,4 +25,4 @@
require File.dirname(__FILE__) + "/gruff/#{filename}"
end
-# TODO bullet
+# TODO bullet
View
12 lib/gruff/bar.rb
@@ -3,6 +3,9 @@
class Gruff::Bar < Gruff::Base
+ # Spacing factor applied between bars
+ attr_accessor :bar_spacing
+
def draw
# Labels will be centered over the left of the bar if
# there are more labels than columns. This is basically the same
@@ -21,9 +24,9 @@ def draw_bars
# Setup spacing.
#
# Columns sit side-by-side.
- spacing_factor = 0.9 # space between the bars
+ @bar_spacing ||= 0.9 # space between the bars
@bar_width = @graph_width / (@column_count * @data.length).to_f
- padding = (@bar_width * (1 - spacing_factor)) / 2
+ padding = (@bar_width * (1 - @bar_spacing)) / 2
@d = @d.stroke_opacity 0.0
@@ -56,7 +59,7 @@ def draw_bars
# Use incremented x and scaled y
# x
left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index))) + padding
- right_x = left_x + @bar_width * spacing_factor
+ right_x = left_x + @bar_width * @bar_spacing
# y
conv = []
conversion.getLeftYRightYscaled( data_point, conv )
@@ -68,8 +71,7 @@ def draw_bars
# Calculate center based on bar_width and current row
label_center = @graph_left +
(@data.length * @bar_width * point_index) +
- (@data.length * @bar_width / 2.0) +
- padding
+ (@data.length * @bar_width / 2.0)
# Subtract half a bar width to center left if requested
draw_label(label_center - (@center_labels_over_point ? @bar_width / 2.0 : 0.0), point_index)
end
View
188 lib/gruff/base.rb
@@ -20,7 +20,7 @@
module Gruff
# This is the version of Gruff you are using.
- VERSION = '0.3.5'
+ VERSION = '0.3.6'
class Base
@@ -36,9 +36,13 @@ class Base
DATA_COLOR_INDEX = 2
# Space around text elements. Mostly used for vertical spacing
- LEGEND_MARGIN = TITLE_MARGIN = LABEL_MARGIN = 10.0
+ LEGEND_MARGIN = TITLE_MARGIN = 20.0
+ LABEL_MARGIN = 10.0
+ DEFAULT_MARGIN = 20.0
DEFAULT_TARGET_WIDTH = 800
+
+ THOUSAND_SEPARATOR = ','
# Blank space above the graph
attr_accessor :top_margin
@@ -51,6 +55,12 @@ class Base
# Blank space to the left of the graph
attr_accessor :left_margin
+
+ # Blank space below the title
+ attr_accessor :title_margin
+
+ # Blank space below the legend
+ attr_accessor :legend_margin
# A hash of names for the individual columns, where the key is the array
# index for the column this label represents.
@@ -170,8 +180,6 @@ class Base
# Looks for Bitstream Vera as the default font. Expects an environment var
# of MAGICK_FONT_PATH to be set. (Uses RMagick's default font otherwise.)
def initialize(target_width=DEFAULT_TARGET_WIDTH)
- @top_margin = @bottom_margin = @left_margin = @right_margin = 20.0
-
if not Numeric === target_width
geometric_width, geometric_height = target_width.split('x')
@columns = geometric_width.to_f
@@ -215,6 +223,10 @@ def initialize_ivars
@marker_font_size = 21.0
@legend_font_size = 20.0
@title_font_size = 36.0
+
+ @top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
+ @legend_margin = LEGEND_MARGIN
+ @title_margin = TITLE_MARGIN
@legend_box_size = 20.0
@@ -253,14 +265,23 @@ def add_color(colorname)
@colors << colorname
end
- # Replace the entire color list with a new array of colors. You need to
- # have one more color than the number of datasets you intend to draw. Also
+ # Replace the entire color list with a new array of colors. Also
# aliased as the colors= setter method.
#
+ # If you specify fewer colors than the number of datasets you intend
+ # to draw, 'increment_color' will cycle through the array, reusing
+ # colors as needed.
+ #
+ # Note that (as with the 'theme' method), you should set up your color
+ # list before you send your data (via the 'data' method). Calls to the
+ # 'data' method made prior to this call will use whatever color scheme
+ # was in place at the time data was called.
+ #
# Example:
# replace_colors ['#cc99cc', '#d9e043', '#34d8a2']
def replace_colors(color_list=[])
@colors = color_list
+ @color_index = 0
end
# You can set a theme manually. Assign a hash to this method before you
@@ -382,14 +403,14 @@ def theme_odeo
def theme_pastel
# Colors
@colors = [
- '#a9dada', # blue
- '#aedaa9', # green
- '#daaea9', # peach
- '#dadaa9', # yellow
- '#a9a9da', # dk purple
- '#daaeda', # purple
- '#dadada' # grey
- ]
+ '#a9dada', # blue
+ '#aedaa9', # green
+ '#daaea9', # peach
+ '#dadaa9', # yellow
+ '#a9a9da', # dk purple
+ '#daaeda', # purple
+ '#dadada' # grey
+ ]
self.theme = {
:colors => @colors,
@@ -403,13 +424,13 @@ def theme_pastel
def theme_greyscale
# Colors
@colors = [
- '#282828', #
- '#383838', #
- '#686868', #
- '#989898', #
- '#c8c8c8', #
- '#e8e8e8', #
- ]
+ '#282828', #
+ '#383838', #
+ '#686868', #
+ '#989898', #
+ '#c8c8c8', #
+ '#e8e8e8', #
+ ]
self.theme = {
:colors => @colors,
@@ -489,7 +510,7 @@ def draw
debug {
# Outer margin
@d.rectangle( @left_margin, @top_margin,
- @raw_columns - @right_margin, @raw_rows - @bottom_margin)
+ @raw_columns - @right_margin, @raw_rows - @bottom_margin)
# Graph area box
@d.rectangle( @graph_left, @graph_top, @graph_right, @graph_bottom)
}
@@ -549,58 +570,58 @@ def calculate_spread # :nodoc:
def setup_graph_measurements
@marker_caps_height = @hide_line_markers ? 0 :
- calculate_caps_height(@marker_font_size)
+ calculate_caps_height(@marker_font_size)
@title_caps_height = @hide_title ? 0 :
- calculate_caps_height(@title_font_size)
+ calculate_caps_height(@title_font_size)
@legend_caps_height = @hide_legend ? 0 :
- calculate_caps_height(@legend_font_size)
+ calculate_caps_height(@legend_font_size)
if @hide_line_markers
(@graph_left,
- @graph_right_margin,
- @graph_bottom_margin) = [@left_margin, @right_margin, @bottom_margin]
+ @graph_right_margin,
+ @graph_bottom_margin) = [@left_margin, @right_margin, @bottom_margin]
else
longest_left_label_width = 0
if @has_left_labels
longest_left_label_width = calculate_width(@marker_font_size,
- labels.values.inject('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
+ labels.values.inject('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
else
longest_left_label_width = calculate_width(@marker_font_size,
- label(@maximum_value.to_f))
+ label(@maximum_value.to_f))
end
# Shift graph if left line numbers are hidden
line_number_width = @hide_line_numbers && !@has_left_labels ?
0.0 :
- (longest_left_label_width + LABEL_MARGIN * 2)
+ (longest_left_label_width + LABEL_MARGIN * 2)
@graph_left = @left_margin +
- line_number_width +
- (@y_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN * 2)
+ line_number_width +
+ (@y_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN * 2)
# Make space for half the width of the rightmost column label.
# Might be greater than the number of columns if between-style bar markers are used.
last_label = @labels.keys.sort.last.to_i
extra_room_for_long_label = (last_label >= (@column_count-1) && @center_labels_over_point) ?
calculate_width(@marker_font_size, @labels[last_label]) / 2.0 :
- 0
+ 0
@graph_right_margin = @right_margin + extra_room_for_long_label
@graph_bottom_margin = @bottom_margin +
- @marker_caps_height + LABEL_MARGIN
+ @marker_caps_height + LABEL_MARGIN
end
@graph_right = @raw_columns - @graph_right_margin
@graph_width = @raw_columns - @graph_left - @graph_right_margin
- # When @hide title, leave a TITLE_MARGIN space for aesthetics.
+ # When @hide title, leave a title_margin space for aesthetics.
# Same with @hide_legend
@graph_top = @top_margin +
- (@hide_title ? TITLE_MARGIN : @title_caps_height + TITLE_MARGIN * 2) +
- (@hide_legend ? LEGEND_MARGIN : @legend_caps_height + LEGEND_MARGIN * 2)
+ (@hide_title ? title_margin : @title_caps_height + title_margin ) +
+ (@hide_legend ? legend_margin : @legend_caps_height + legend_margin)
x_axis_label_height = @x_axis_label.nil? ? 0.0 :
- @marker_caps_height + LABEL_MARGIN
+ @marker_caps_height + LABEL_MARGIN
@graph_bottom = @raw_rows - @graph_bottom_margin - x_axis_label_height
@graph_height = @graph_bottom - @graph_top
end
@@ -620,9 +641,9 @@ def draw_axis_labels
@d.pointsize = scale_fontsize(@marker_font_size)
@d.gravity = NorthGravity
@d = @d.annotate_scaled( @base_image,
- @raw_columns, 1.0,
- 0.0, x_axis_label_y_coordinate,
- @x_axis_label, @scale)
+ @raw_columns, 1.0,
+ 0.0, x_axis_label_y_coordinate,
+ @x_axis_label, @scale)
debug { @d.line 0.0, x_axis_label_y_coordinate, @raw_columns, x_axis_label_y_coordinate }
end
@@ -631,9 +652,9 @@ def draw_axis_labels
@d.rotation = 90.0
@d.gravity = CenterGravity
@d = @d.annotate_scaled( @base_image,
- 1.0, @raw_rows,
- @left_margin + @marker_caps_height / 2.0, 0.0,
- @y_axis_label, @scale)
+ 1.0, @raw_rows,
+ @left_margin + @marker_caps_height / 2.0, 0.0,
+ @y_axis_label, @scale)
@d.rotation = -90.0
end
end
@@ -688,9 +709,9 @@ def draw_line_markers
# Vertically center with 1.0 for the height
@d = @d.annotate_scaled( @base_image,
- @graph_left - LABEL_MARGIN, 1.0,
- 0.0, y,
- label(marker_label), @scale)
+ @graph_left - LABEL_MARGIN, 1.0,
+ 0.0, y,
+ label(marker_label), @scale)
end
end
@@ -764,8 +785,8 @@ def draw_legend
current_x_offset = center(sum(label_widths.first))
current_y_offset = @hide_title ?
- @top_margin + LEGEND_MARGIN :
- @top_margin + TITLE_MARGIN + @title_caps_height + LEGEND_MARGIN
+ @top_margin + title_margin :
+ @top_margin + title_margin + @title_caps_height
@legend_labels.each_with_index do |legend_label, index|
@@ -777,17 +798,17 @@ def draw_legend
@d.font_weight = NormalWeight
@d.gravity = WestGravity
@d = @d.annotate_scaled( @base_image,
- @raw_columns, 1.0,
- current_x_offset + (legend_square_width * 1.7), current_y_offset,
- legend_label.to_s, @scale)
+ @raw_columns, 1.0,
+ current_x_offset + (legend_square_width * 1.7), current_y_offset,
+ legend_label.to_s, @scale)
# Now draw box with color of this dataset
@d = @d.stroke('transparent')
@d = @d.fill @data[index][DATA_COLOR_INDEX]
@d = @d.rectangle(current_x_offset,
- current_y_offset - legend_square_width / 2.0,
- current_x_offset + legend_square_width,
- current_y_offset + legend_square_width / 2.0)
+ current_y_offset - legend_square_width / 2.0,
+ current_x_offset + legend_square_width,
+ current_y_offset + legend_square_width / 2.0)
@d.pointsize = @legend_font_size
metrics = @d.get_type_metrics(@base_image, legend_label.to_s)
@@ -800,7 +821,7 @@ def draw_legend
label_widths.shift
current_x_offset = center(sum(label_widths.first)) unless label_widths.empty?
- line_height = [@legend_caps_height, legend_square_width].max + LEGEND_MARGIN
+ line_height = [@legend_caps_height, legend_square_width].max + legend_margin
if label_widths.length > 0
# Wrap to next line and shrink available graph dimensions
current_y_offset += line_height
@@ -825,9 +846,9 @@ def draw_title
@d.font_weight = BoldWeight
@d.gravity = NorthGravity
@d = @d.annotate_scaled( @base_image,
- @raw_columns, 1.0,
- 0, @top_margin,
- @title, @scale)
+ @raw_columns, 1.0,
+ 0, @top_margin,
+ @title, @scale)
end
# Draws column labels below graph, centered over x_offset
@@ -846,9 +867,9 @@ def draw_label(x_offset, index)
@d.pointsize = scale_fontsize(@marker_font_size)
@d.gravity = NorthGravity
@d = @d.annotate_scaled(@base_image,
- 1.0, 1.0,
- x_offset, y_offset,
- @labels[index], @scale)
+ 1.0, 1.0,
+ x_offset, y_offset,
+ @labels[index], @scale)
@labels_seen[index] = 1
debug { @d.line 0.0, y_offset, @raw_columns, y_offset }
end
@@ -863,9 +884,9 @@ def draw_no_data
@d.pointsize = scale_fontsize(80)
@d.gravity = CenterGravity
@d = @d.annotate_scaled( @base_image,
- @raw_columns, @raw_rows/2.0,
- 0, 10,
- @no_data_message, @scale)
+ @raw_columns, @raw_rows/2.0,
+ 0, 10,
+ @no_data_message, @scale)
end
# Finds the best background to render based on the provided theme options.
@@ -892,7 +913,7 @@ def render_solid_background(color)
# Use with a theme definition method to draw a gradiated background.
def render_gradiated_background(top_color, bottom_color)
Image.new(@columns, @rows,
- GradientFill.new(0, 0, 100, 0, top_color, bottom_color))
+ GradientFill.new(0, 0, 100, 0, top_color, bottom_color))
end
# Use with a theme to use an image (800x600 original) background.
@@ -1033,37 +1054,28 @@ def debug
end
end
- # Uses the next color in your color list.
+ # Returns the next color in your color list.
def increment_color
- if @color_index == 0
- @color_index += 1
- return @colors[0]
- else
- if @color_index < @colors.length
- @color_index += 1
- return @colors[@color_index - 1]
- else
- # Start over
- @color_index = 0
- return @colors[-1]
- end
- end
+ @color_index = (@color_index + 1) % @colors.length
+ return @colors[@color_index - 1]
end
# Return a formatted string representing a number value that should be
# printed as a label.
def label(value)
- if (@spread.to_f % @marker_count.to_f == 0) || !@y_axis_increment.nil?
- return value.to_i.to_s
- end
-
- if @spread > 10.0
+ label = if (@spread.to_f % @marker_count.to_f == 0) || !@y_axis_increment.nil?
+ value.to_i.to_s
+ elsif @spread > 10.0
sprintf("%0i", value)
elsif @spread >= 3.0
sprintf("%0.2f", value)
else
value.to_s
end
+
+ parts = label.split('.')
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{THOUSAND_SEPARATOR}")
+ parts.join('.')
end
# Returns the height of the capital letter 'X' for the current font and
@@ -1101,9 +1113,9 @@ def annotate_scaled(img, width, height, x, y, text, scale)
scaled_height = (height * scale) >= 1 ? (height * scale) : 1
self.annotate( img,
- scaled_width, scaled_height,
- x * scale, y * scale,
- text)
+ scaled_width, scaled_height,
+ x * scale, y * scale,
+ text)
end
end
View
113 lib/gruff/dot.rb
@@ -0,0 +1,113 @@
+require File.dirname(__FILE__) + '/base'
+
+##
+# Graph with dots and labels along a vertical access
+# see: 'Creating More Effective Graphs' by Robbins
+
+class Gruff::Dot < Gruff::Base
+
+ def draw
+ @has_left_labels = true
+ super
+
+ return unless @has_data
+
+ # Setup spacing.
+ #
+ spacing_factor = 1.0
+
+ @items_width = @graph_height / @column_count.to_f
+ @item_width = @items_width * spacing_factor / @norm_data.size
+ @d = @d.stroke_opacity 0.0
+ height = Array.new(@column_count, 0)
+ length = Array.new(@column_count, @graph_left)
+ padding = (@items_width * (1 - spacing_factor)) / 2
+
+ @norm_data.each_with_index do |data_row, row_index|
+ data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
+
+ x_pos = @graph_left + (data_point * @graph_width) - (@item_width.to_f/6.0).round
+ y_pos = @graph_top + (@items_width * point_index) + padding + (@item_width.to_f/2.0).round
+
+ if row_index == 0
+ @d = @d.stroke(@marker_color)
+ @d = @d.stroke_width 1.0
+ @d = @d.opacity 0.1
+ @d = @d.line(@graph_left, y_pos, @graph_left + @graph_width, y_pos)
+ end
+
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
+ @d = @d.stroke('transparent')
+ @d = @d.circle(x_pos, y_pos, x_pos + (@item_width.to_f/3.0).round, y_pos)
+
+ # Calculate center based on item_width and current row
+ label_center = @graph_top + (@items_width * point_index + @items_width / 2) + padding
+ draw_label(label_center, point_index)
+ end
+
+ end
+
+ @d.draw(@base_image)
+ end
+
+protected
+
+ # Instead of base class version, draws vertical background lines and label
+ def draw_line_markers
+
+ return if @hide_line_markers
+
+ @d = @d.stroke_antialias false
+
+ # Draw horizontal line markers and annotate with numbers
+ @d = @d.stroke(@marker_color)
+ @d = @d.stroke_width 1
+ number_of_lines = 5
+
+ # TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
+ increment = significant(@maximum_value.to_f / number_of_lines)
+ (0..number_of_lines).each do |index|
+
+ line_diff = (@graph_right - @graph_left) / number_of_lines
+ x = @graph_right - (line_diff * index) - 1
+ @d = @d.line(x, @graph_bottom, x, @graph_bottom + 0.5 * LABEL_MARGIN)
+ diff = index - number_of_lines
+ marker_label = diff.abs * increment
+
+ unless @hide_line_numbers
+ @d.fill = @font_color
+ @d.font = @font if @font
+ @d.stroke = 'transparent'
+ @d.pointsize = scale_fontsize(@marker_font_size)
+ @d.gravity = CenterGravity
+ # TODO Center text over line
+ @d = @d.annotate_scaled( @base_image,
+ 0, 0, # Width of box to draw text in
+ x, @graph_bottom + (LABEL_MARGIN * 2.0), # Coordinates of text
+ marker_label.to_s, @scale)
+ end # unless
+ @d = @d.stroke_antialias true
+ end
+ end
+
+ ##
+ # Draw on the Y axis instead of the X
+
+ def draw_label(y_offset, index)
+ if !@labels[index].nil? && @labels_seen[index].nil?
+ @d.fill = @font_color
+ @d.font = @font if @font
+ @d.stroke = 'transparent'
+ @d.font_weight = NormalWeight
+ @d.pointsize = scale_fontsize(@marker_font_size)
+ @d.gravity = EastGravity
+ @d = @d.annotate_scaled(@base_image,
+ 1, 1,
+ -@graph_left + LABEL_MARGIN * 2.0, y_offset,
+ @labels[index], @scale)
+ @labels_seen[index] = 1
+ end
+ end
+
+end
+
View
52 lib/gruff/line.rb
@@ -16,10 +16,14 @@ class Gruff::Line < Gruff::Base
# Draw a dashed line at the given value
attr_accessor :baseline_value
-
+
# Color of the baseline
attr_accessor :baseline_color
+ # Dimensions of lines and dots; calculated based on dataset size if left unspecified
+ attr_accessor :line_width
+ attr_accessor :dot_radius
+
# Hide parts of the graph to fit more datapoints, or for a different appearance.
attr_accessor :hide_dots, :hide_lines
@@ -30,7 +34,7 @@ class Gruff::Line < Gruff::Base
# g = Gruff::Line.new(400, false) # 400px wide, no lines (for backwards compatibility)
#
# g = Gruff::Line.new(false) # Defaults to 800px wide, no lines (for backwards compatibility)
- #
+ #
# The preferred way is to call hide_dots or hide_lines instead.
def initialize(*args)
raise ArgumentError, "Wrong number of arguments" if args.length > 2
@@ -39,7 +43,7 @@ def initialize(*args)
else
super args.shift
end
-
+
@hide_dots = @hide_lines = false
@baseline_color = 'red'
@baseline_value = nil
@@ -49,10 +53,10 @@ def draw
super
return unless @has_data
-
- # Check to see if more than one datapoint was given. NaN can result otherwise.
+
+ # Check to see if more than one datapoint was given. NaN can result otherwise.
@x_increment = (@column_count > 1) ? (@graph_width / (@column_count - 1).to_f) : @graph_width
-
+
if (defined?(@norm_baseline)) then
level = @graph_top + (@graph_height - @norm_baseline * @graph_height)
@d = @d.push
@@ -64,9 +68,11 @@ def draw
@d = @d.pop
end
- @norm_data.each do |data_row|
+ @norm_data.each do |data_row|
prev_x = prev_y = nil
+ @one_point = contains_one_point_only?(data_row)
+
data_row[DATA_VALUES_INDEX].each_with_index do |data_point, index|
new_x = @graph_left + (@x_increment * index)
next if data_point.nil?
@@ -79,12 +85,19 @@ def draw
@d = @d.stroke data_row[DATA_COLOR_INDEX]
@d = @d.fill data_row[DATA_COLOR_INDEX]
@d = @d.stroke_opacity 1.0
- @d = @d.stroke_width clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 4), 5.0)
+ @d = @d.stroke_width line_width ||
+ clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 4), 5.0)
+
- if !@hide_lines and !prev_x.nil? and !prev_y.nil? then
+ circle_radius = dot_radius ||
+ clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 2.5), 5.0)
+
+ if !@hide_lines and !prev_x.nil? and !prev_y.nil? then
@d = @d.line(prev_x, prev_y, new_x, new_y)
+ elsif @one_point
+ # Show a circle if there's just one_point
+ @d = @d.circle(new_x, new_y, new_x - circle_radius, new_y)
end
- circle_radius = clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 2.5), 5.0)
@d = @d.circle(new_x, new_y, new_x - circle_radius, new_y) unless @hide_dots
prev_x = new_x
@@ -101,5 +114,22 @@ def normalize
super
@norm_baseline = (@baseline_value.to_f / @maximum_value.to_f) if @baseline_value
end
-
+
+ def contains_one_point_only?(data_row)
+ # Spin through data to determine if there is just one_value present.
+ one_point = false
+ data_row[DATA_VALUES_INDEX].each do |data_point|
+ if !data_point.nil?
+ if one_point
+ # more than one point, bail
+ return false
+ else
+ # there is at least one data point
+ return true
+ end
+ end
+ end
+ return one_point
+ end
+
end
View
7 lib/gruff/mini/bar.rb
@@ -9,15 +9,20 @@ class Bar < Gruff::Bar
include Gruff::Mini::Legend
- def draw
+ def initialize_ivars
+ super
+
@hide_legend = true
@hide_title = true
@hide_line_numbers = true
@marker_font_size = 50.0
@minimum_value = 0.0
+ @maximum_value = 0.0
@legend_font_size = 60.0
+ end
+ def draw
expand_canvas_for_vertical_legend
super
View
9 lib/gruff/mini/legend.rb
@@ -2,10 +2,14 @@ module Gruff
module Mini
module Legend
+ attr_accessor :hide_mini_legend
+
##
# The canvas needs to be bigger so we can put the legend beneath it.
def expand_canvas_for_vertical_legend
+ return if @hide_mini_legend
+
@original_rows = @raw_rows
@rows += @data.length * calculate_caps_height(scale_fontsize(@legend_font_size)) * 1.7
render_background
@@ -15,7 +19,8 @@ def expand_canvas_for_vertical_legend
# Draw the legend beneath the existing graph.
def draw_vertical_legend
-
+ return if @hide_mini_legend
+
@legend_labels = @data.collect {|item| item[Gruff::Base::DATA_LABEL_INDEX] }
legend_square_width = 40.0 # small square with color of this item
@@ -69,7 +74,7 @@ def truncate_legend_label(label)
while calculate_width(scale_fontsize(@legend_font_size), truncated_label) > (@columns - @legend_left_margin - @right_margin) && (truncated_label.length > 1)
truncated_label = truncated_label[0..truncated_label.length-2]
end
- truncated_label + (truncated_label.length < label.to_s.length ? "" : '')
+ truncated_label + (truncated_label.length < label.to_s.length ? "..." : '')
end
end
View
10 lib/gruff/net.rb
@@ -6,6 +6,10 @@ class Gruff::Net < Gruff::Base
# Hide parts of the graph to fit more datapoints, or for a different appearance.
attr_accessor :hide_dots
+
+ # Dimensions of lines and dots; calculated based on dataset size if left unspecified
+ attr_accessor :line_width
+ attr_accessor :dot_radius
def initialize(*args)
super
@@ -25,10 +29,12 @@ def draw
@center_y = @graph_top + (@graph_height / 2.0) - 10 # Move graph up a bit
@x_increment = @graph_width / (@column_count - 1).to_f
- circle_radius = clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 2.5), 5.0)
+ circle_radius = dot_radius ||
+ clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 2.5), 5.0)
@d = @d.stroke_opacity 1.0
- @d = @d.stroke_width clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 4), 5.0)
+ @d = @d.stroke_width line_width ||
+ clip_value_if_greater_than(@columns / (@norm_data.first[DATA_VALUES_INDEX].size * 4), 5.0)
if (defined?(@norm_baseline)) then
level = @graph_top + (@graph_height - @norm_baseline * @graph_height)
View
14 lib/gruff/pie.rb
@@ -18,10 +18,14 @@ class Gruff::Pie < Gruff::Base
# Can be used to make the pie start cutting slices at the top (-90.0)
# or at another angle. Default is 0.0, which starts at 3 o'clock.
attr_accessor :zero_degree
+ # Do not show labels for slices that are less than this percent. Use 0 to always show all labels.
+ # Defaults to 0
+ attr_accessor :hide_labels_less_than
def initialize_ivars
super
@zero_degree = 0.0
+ @hide_labels_less_than = 0.0
end
def draw
@@ -58,17 +62,15 @@ def draw
half_angle = prev_degrees + ((prev_degrees + current_degrees) - prev_degrees) / 2
- # Following line is commented to allow display of the percentiles
- # bug appeared between r90 and r92
- # unless @hide_line_markers then
+ label_val = ((data_row[DATA_VALUES_INDEX].first / total_sum) * 100.0).round
+ unless label_val < @hide_labels_less_than
# End the string with %% to escape the single %.
# RMagick must use sprintf with the string and % has special significance.
- label_string = ((data_row[DATA_VALUES_INDEX].first / total_sum) *
- 100.0).round.to_s + '%%'
+ label_string = label_val.to_s + '%%'
@d = draw_label(center_x,center_y, half_angle,
radius + (radius * TEXT_OFFSET_PERCENTAGE),
label_string)
- # end
+ end
prev_degrees += current_degrees
end
View
11 lib/gruff/side_bar.rb
@@ -5,6 +5,9 @@
class Gruff::SideBar < Gruff::Base
+ # Spacing factor applied between bars
+ attr_accessor :bar_spacing
+
def draw
@has_left_labels = true
super
@@ -13,14 +16,14 @@ def draw
# Setup spacing.
#
- spacing_factor = 0.9
+ @bar_spacing ||= 0.9
@bars_width = @graph_height / @column_count.to_f
- @bar_width = @bars_width * spacing_factor / @norm_data.size
+ @bar_width = @bars_width * @bar_spacing / @norm_data.size
@d = @d.stroke_opacity 0.0
height = Array.new(@column_count, 0)
length = Array.new(@column_count, @graph_left)
- padding = (@bars_width * (1 - spacing_factor)) / 2
+ padding = (@bars_width * (1 - @bar_spacing)) / 2
@norm_data.each_with_index do |data_row, row_index|
@d = @d.fill data_row[DATA_COLOR_INDEX]
@@ -44,7 +47,7 @@ def draw
@d = @d.rectangle(left_x, left_y, right_x, right_y)
# Calculate center based on bar_width and current row
- label_center = @graph_top + (@bars_width * point_index + @bars_width / 2) + padding
+ label_center = @graph_top + (@bars_width * point_index + @bars_width / 2)
draw_label(label_center, point_index)
end
View
11 lib/gruff/side_stacked_bar.rb
@@ -11,6 +11,9 @@
class Gruff::SideStackedBar < Gruff::SideBar
include StackedMixin
+ # Spacing factor applied between bars
+ attr_accessor :bar_spacing
+
def draw
@has_left_labels = true
get_maximum_by_stack
@@ -21,13 +24,13 @@ def draw
# Setup spacing.
#
# Columns sit stacked.
- spacing_factor = 0.9
+ @bar_spacing ||= 0.9
@bar_width = @graph_height / @column_count.to_f
@d = @d.stroke_opacity 0.0
height = Array.new(@column_count, 0)
length = Array.new(@column_count, @graph_left)
- padding = (@bar_width * (1 - spacing_factor)) / 2
+ padding = (@bar_width * (1 - @bar_spacing)) / 2
@norm_data.each_with_index do |data_row, row_index|
@d = @d.fill data_row[DATA_COLOR_INDEX]
@@ -45,14 +48,14 @@ def draw
left_x = length[point_index] #+ 1
left_y = @graph_top + (@bar_width * point_index) + padding
right_x = left_x + difference
- right_y = left_y + @bar_width * spacing_factor
+ right_y = left_y + @bar_width * @bar_spacing
length[point_index] += difference
height[point_index] += (data_point * @graph_width - 2)
@d = @d.rectangle(left_x, left_y, right_x, right_y)
# Calculate center based on bar_width and current row
- label_center = @graph_top + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0) + padding
+ label_center = @graph_top + (@bar_width * point_index) + (@bar_width * @bar_spacing / 2.0)
draw_label(label_center, point_index)
end
View
11 lib/gruff/stacked_bar.rb
@@ -5,6 +5,9 @@
class Gruff::StackedBar < Gruff::Base
include StackedMixin
+ # Spacing factor applied between bars
+ attr_accessor :bar_spacing
+
# Draws a bar graph, but multiple sets are stacked on top of each other.
def draw
get_maximum_by_stack
@@ -14,9 +17,9 @@ def draw
# Setup spacing.
#
# Columns sit stacked.
- spacing_factor = 0.9
+ @bar_spacing ||= 0.9
@bar_width = @graph_width / @column_count.to_f
- padding = (@bar_width * (1 - spacing_factor)) / 2
+ padding = (@bar_width * (1 - @bar_spacing)) / 2
@d = @d.stroke_opacity 0.0
@@ -27,7 +30,7 @@ def draw
@d = @d.fill data_row[DATA_COLOR_INDEX]
# Calculate center based on bar_width and current row
- label_center = @graph_left + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0) + padding
+ label_center = @graph_left + (@bar_width * point_index) + (@bar_width * @bar_spacing / 2.0)
draw_label(label_center, point_index)
next if (data_point == 0)
@@ -36,7 +39,7 @@ def draw
left_y = @graph_top + (@graph_height -
data_point * @graph_height -
height[point_index]) + 1
- right_x = left_x + @bar_width * spacing_factor
+ right_x = left_x + @bar_width * @bar_spacing
right_y = @graph_top + @graph_height - height[point_index] - 1
# update the total height of the current stacked bar
View
23 test/test_bar.rb
@@ -20,6 +20,7 @@ def setup
def test_bar_graph
g = setup_basic_graph
g.title = "Bar Graph Test"
+ g.title_margin = 100
g.write("test/output/bar_keynote.png")
g = setup_basic_graph
@@ -32,10 +33,20 @@ def test_bar_graph
g.theme_odeo
g.write("test/output/bar_odeo.png")
end
+
+ def test_thousand_separators
+ g = Gruff::Bar.new(600)
+ g.title = "Formatted numbers"
+ g.bar_spacing = 0.2
+ g.marker_count = 8
+ g.data("data", [4025, 1024, 50257, 703672, 1580456])
+ g.write("test/output/bar_formatted_numbers.png")
+ end
def test_bar_graph_set_colors
g = Gruff::Bar.new
g.title = "Bar Graph With Manual Colors"
+ g.legend_margin = 50
g.labels = {
0 => '5/6',
1 => '5/15',
@@ -248,6 +259,18 @@ def test_custom_theme
g.minimum_value = 0
g.write("test/output/bar_themed.png")
end
+
+ def test_legend_should_not_overlap
+ g = Gruff::Bar.new(400)
+ g.theme_37signals()
+ g.title = 'My Graph'
+ g.data("Apples Oranges Watermelon Apples Oranges", [1, 2, 3, 4, 4, 3])
+ g.data('Oranges', [4, 8, 7, 9, 8, 9])
+ g.data('Watermelon', [2, 3, 1, 5, 6, 8])
+ g.data('Peaches', [9, 9, 10, 8, 7, 9])
+ g.labels = {0 => '2003', 2 => '2004', 4 => '2005'}
+ g.write("test/output/bar_long_legend_text.png")
+ end
def test_july_enhancements
g = Gruff::Bar.new(600)
View
273 test/test_dot.rb
@@ -0,0 +1,273 @@
+#!/usr/bin/ruby
+
+require File.dirname(__FILE__) + "/gruff_test_case"
+
+class TestGruffDot < GruffTestCase
+
+ # TODO Delete old output files once when starting tests
+
+ def setup
+ @datasets = [
+ [:Jimmy, [25, 36, 86, 39]],
+ [:Charles, [80, 54, 67, 54]],
+ [:Julie, [22, 29, 35, 38]],
+ #[:Jane, [95, 95, 95, 90, 85, 80, 88, 100]],
+ #[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
+ #["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
+ ]
+ end
+
+ def test_dot_graph
+ g = setup_basic_graph
+ g.title = "Dot Graph Test"
+ g.write("test/output/dot_keynote.png")
+ end
+
+ def test_dot_graph_set_colors
+ g = Gruff::Dot.new
+ g.title = "Dot Graph With Manual Colors"
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ g.data(:Art, [0, 5, 8, 15], '#990000')
+ g.data(:Philosophy, [10, 3, 2, 8], '#009900')
+ g.data(:Science, [2, 15, 8, 11], '#990099')
+
+ g.minimum_value = 0
+
+ g.write("test/output/dot_manual_colors.png")
+ end
+
+ def test_dot_graph_small
+ g = Gruff::Dot.new(400)
+ g.title = "Visual Multi-Line Dot Graph Test"
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ @datasets.each do |data|
+ g.data(data[0], data[1])
+ end
+
+ g.write("test/output/dot_keynote_small.png")
+ end
+
+ # Somewhat worthless test. Should an error be thrown?
+ # def test_nil_font
+ # g = setup_basic_graph 400
+ # g.title = "Nil Font"
+ # g.font = nil
+ # g.write "test/output/dot_nil_font.png"
+ # end
+
+
+ def test_no_line_markers
+ g = setup_basic_graph(400)
+ g.title = "No Line Markers"
+ g.hide_line_markers = true
+ g.write("test/output/dot_no_line_markers.png")
+ end
+
+ def test_no_legend
+ g = setup_basic_graph(400)
+ g.title = "No Legend"
+ g.hide_legend = true
+ g.write("test/output/dot_no_legend.png")
+ end
+
+ def test_no_title
+ g = setup_basic_graph(400)
+ g.title = "No Title"
+ g.hide_title = true
+ g.write("test/output/dot_no_title.png")
+ end
+
+ def test_no_title_or_legend
+ g = setup_basic_graph(400)
+ g.title = "No Title or Legend"
+ g.hide_legend = true
+ g.hide_title = true
+ g.write("test/output/dot_no_title_or_legend.png")
+ end
+
+ def test_set_marker_count
+ g = setup_basic_graph(400)
+ g.title = "Set marker"
+ g.marker_count = 10
+ g.write("test/output/dot_set_marker.png")
+ end
+
+ def test_set_legend_box_size
+ g = setup_basic_graph(400)
+ g.title = "Set Small Legend Box Size"
+ g.legend_box_size = 10.0
+ g.write("test/output/dot_set_legend_box_size_sm.png")
+
+ g = setup_basic_graph(400)
+ g.title = "Set Large Legend Box Size"
+ g.legend_box_size = 50.0
+ g.write("test/output/dot_set_legend_box_size_lg.png")
+ end
+
+ def test_x_y_labels
+ g = setup_basic_graph(400)
+ g.title = "X Y Labels"
+ g.x_axis_label = 'Score (%)'
+ g.y_axis_label = "Students"
+ g.write("test/output/dot_x_y_labels.png")
+ end
+
+ def test_wide_graph
+ g = setup_basic_graph('800x400')
+ g.title = "Wide Graph"
+ g.write("test/output/dot_wide_graph.png")
+
+ g = setup_basic_graph('400x200')
+ g.title = "Wide Graph Small"
+ g.write("test/output/dot_wide_graph_small.png")
+ end
+
+
+ def test_tall_graph
+ g = setup_basic_graph('400x600')
+ g.title = "Tall Graph"
+ g.write("test/output/dot_tall_graph.png")
+
+ g = setup_basic_graph('200x400')
+ g.title = "Tall Graph Small"
+ g.write("test/output/dot_tall_graph_small.png")
+ end
+
+
+ def test_one_value
+ g = Gruff::Dot.new
+ g.title = "One Value Graph Test"
+ g.labels = {
+ 0 => '1',
+ 1 => '2'
+ }
+ g.data('one', [1,1])
+
+ g.write("test/output/dot_one_value.png")
+ end
+
+
+ def test_negative
+ g = Gruff::Dot.new
+ g.title = "Pos/Neg Dot Graph Test"
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ g.data(:apples, [-1, 0, 4, -4])
+ g.data(:peaches, [10, 8, 6, 3])
+
+ g.write("test/output/dot_pos_neg.png")
+ end
+
+
+ def test_nearly_zero
+ g = Gruff::Dot.new
+ g.title = "Nearly Zero Graph"
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ g.data(:apples, [1, 2, 3, 4])
+ g.data(:peaches, [4, 3, 2, 1])
+ g.minimum_value = 0
+ g.maximum_value = 10
+ g.write("test/output/dot_nearly_zero_max_10.png")
+ end
+
+ def test_y_axis_increment
+ generate_with_y_axis_increment 2.0
+ generate_with_y_axis_increment 1
+ generate_with_y_axis_increment 5
+ generate_with_y_axis_increment 20
+ end
+
+ def generate_with_y_axis_increment(increment)
+ g = Gruff::Dot.new
+ g.title = "Y Axis Set to #{increment}"
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ g.y_axis_increment = increment
+ g.data(:apples, [1, 0.2, 0.5, 0.7])
+ g.data(:peaches, [2.5, 2.3, 2, 6.1])
+ g.write("test/output/dot_y_increment_#{increment}.png")
+ end
+
+
+ def test_custom_theme
+ g = Gruff::Dot.new
+ g.title = "Custom Theme"
+ g.font = File.expand_path('CREABBRG.TTF', ENV['MAGICK_FONT_PATH'])
+ g.title_font_size = 60
+ g.legend_font_size = 32
+ g.marker_font_size = 32
+ g.theme = {
+ :colors => %w(#efd250 #666699 #e5573f #9595e2),
+ :marker_color => 'white',
+ :font_color => 'blue',
+ :background_image => "assets/pc306715.jpg"
+ }
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ g.data(:vancouver, [1, 2, 3, 4])
+ g.data(:seattle, [2, 4, 6, 8])
+ g.data(:portland, [3, 1, 7, 3])
+ g.data(:victoria, [4, 3, 5, 7])
+ g.minimum_value = 0
+ g.write("test/output/dot_themed.png")
+ end
+
+ def test_july_enhancements
+ g = Gruff::Dot.new(600)
+ g.hide_legend = true
+ g.title = "Full speed ahead"
+ g.labels = (0..10).inject({}) { |memo, i| memo.merge({ i => (i*10).to_s}) }
+ g.data(:apples, (0..9).map { rand(20)/10.0 })
+ g.y_axis_increment = 1.0
+ g.x_axis_label = 'Score (%)'
+ g.y_axis_label = 'Students'
+ write_test_file g, 'enhancements.png'
+ end
+
+
+protected
+
+ def setup_basic_graph(size=800)
+ g = Gruff::Dot.new(size)
+ g.title = "My Dot Graph"
+ g.labels = {
+ 0 => '5/6',
+ 1 => '5/15',
+ 2 => '5/24',
+ 3 => '5/30',
+ }
+ @datasets.each do |data|
+ g.data(data[0], data[1])
+ end
+ g
+ end
+
+end
+
View
51 test/test_line.rb
@@ -132,6 +132,8 @@ def test_line_large_values
g.title = "Very Large Values Line Graph Test"
g.baseline_value = 50_000
g.baseline_color = 'green'
+ g.dot_radius = 15
+ g.line_width = 3
@datasets.each do |data|
g.data(data[0], data[1])
end
@@ -147,9 +149,20 @@ def test_line_large_values
#
# end
#
- # def test_request_too_many_colors
- #
- # end
+
+ def test_request_too_many_colors
+ g = Gruff::Line.new
+ g.title = "More Sets Than in Color Array"
+# g.theme = {} # Sets theme with only black and white
+ @datasets.each do |data|
+ g.data(data[0], data[1])
+ end
+ @datasets.each do |data|
+ g.data("#{data[0]}-B", data[1].map {|d| d + 20})
+ end
+ g.write("test/output/line_more_sets_than_colors.png")
+ end
+
#
# def test_add_data
#
@@ -435,8 +448,38 @@ def test_no_hide_line_no_labels
g.hide_line_markers = false
g.write('test/output/line_no_hide.png')
end
+
-protected
+ def test_jruby_error
+ g = Gruff::Line.new
+ g.theme = {
+ :colors => ['#7F0099', '#2F85ED', '#2FED09','#EC962F'],
+ :marker_color => '#aaa',
+ :background_colors => ['#E8E8E8','#B9FD6C']
+ }
+ g.hide_title = true
+
+ g.legend_font_size = 12
+ g.marker_font_size = 16
+ g.hide_dots = false
+ g.label_max_decimals = 1
+
+ g.write('test/output/line_jruby_error.png')
+ end
+
+private
+
+ def bmi(params={})
+ g = basic_graph()
+
+ g.y_axis_label = 'BMI'
+
+ bmis = [24.3, 23.9, 23.7, 23.7, 23.6, 23.9, 23.6, 23.7, 23.4, 23.4, 23.4, 22.9]
+
+ g.data( 'BMI', bmis )
+ g.hide_legend = true
+ return g
+ end
# TODO Reset data after each theme
def line_graph_with_themes(size=nil)
View
1 test/test_mini_bar.rb
@@ -6,6 +6,7 @@ class TestMiniBar < GruffTestCase
def test_simple_bar
setup_single_dataset
g = setup_basic_graph(Gruff::Mini::Bar, 200)
+ g.hide_mini_legend = true
write_test_file g, 'mini_bar.png'
end

0 comments on commit ef73ab9

Please sign in to comment.
Something went wrong with that request. Please try again.