Skip to content

Commit

Permalink
Merge pull request #12 from BRIMIL01/bar_updates
Browse files Browse the repository at this point in the history
Bar updates
  • Loading branch information
donv committed Nov 29, 2012
2 parents 104d361 + 5259be2 commit cf1e090
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 12 deletions.
5 changes: 5 additions & 0 deletions lib/gruff/bar.rb
Expand Up @@ -88,8 +88,13 @@ def draw_bars
label_center = @graph_left +
(@data.length * @bar_width * point_index) +
(@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)
if @show_labels_for_bar_values
val = (@label_formatting || "%.2f") % @norm_data[row_index][3][point_index]
draw_value_label(left_x + (right_x - left_x)/2, conv[0]-30, val.commify, true)
end
end

end
Expand Down
66 changes: 62 additions & 4 deletions lib/gruff/base.rb
Expand Up @@ -96,7 +96,7 @@ class Base
# How truncated labels visually appear if they exceed label_max_size
# :absolute - does not show trailing dots to indicate truncation. This is
# the default.
# :trailing_dots - shows trailing dots to indicate truncation (note
# :trailing_dots - shows trailing dots to indicate truncation (note
# that label_max_size must be greater than 3).
attr_accessor :label_truncation_style

Expand Down Expand Up @@ -185,6 +185,17 @@ class Base
# Will be scaled down if graph is smaller than 800px wide.
attr_accessor :legend_box_size

# Output the values for the bars on a bar graph
# Default is false
attr_accessor :show_labels_for_bar_values

# Set the number output format for labels using sprintf
# Default is "%.2f"
attr_accessor :label_formatting

# With Side Bars use the data label for the marker value to the left of the bar
# Default is false
attr_accessor :use_data_label
# If one numerical argument is given, the graph is drawn at 4/3 ratio
# according to the given width (800 results in 800x600, 400 gives 400x300,
# etc.).
Expand Down Expand Up @@ -246,7 +257,7 @@ def initialize_ivars

@no_data_message = "No Data"

@hide_line_markers = @hide_legend = @hide_title = @hide_line_numbers = @legend_at_bottom = false
@hide_line_markers = @hide_legend = @hide_title = @hide_line_numbers = @legend_at_bottom = @show_labels_for_bar_values = false
@center_labels_over_point = true
@has_left_labels = false
@label_stagger_height = 0
Expand Down Expand Up @@ -473,7 +484,7 @@ def normalize(force=false)
norm_data_points << ((data_point.to_f - @minimum_value.to_f) / @spread)
end
end
@norm_data << [data_row[DATA_LABEL_INDEX], norm_data_points, data_row[DATA_COLOR_INDEX]]
@norm_data << [data_row[DATA_LABEL_INDEX], norm_data_points, data_row[DATA_COLOR_INDEX], data_row[DATA_VALUES_INDEX]]
end
end
end
Expand Down Expand Up @@ -597,7 +608,7 @@ def draw_line_markers
end
@marker_count ||= 4
end
@increment = (@spread > 0) ? significant(@spread / @marker_count) : 1
@increment = (@spread > 0 && @marker_count > 0) ? significant(@spread / @marker_count) : 1
else
# TODO Make this work for negative values
@maximum_value = [@maximum_value.ceil, @y_axis_increment].max
Expand Down Expand Up @@ -816,6 +827,46 @@ def draw_label(x_offset, index)
debug { @d.line 0.0, y_offset, @raw_columns, y_offset }
end
end

# Draws the data value over the data point in bar graphs
def draw_value_label(x_offset, y_offset, data_point, bar_value=false)
return if @hide_line_markers && !bar_value

#y_offset = @graph_bottom + LABEL_MARGIN

@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 = NorthGravity
@d = @d.annotate_scaled(@base_image,
1.0, 1.0,
x_offset, y_offset,
data_point.to_s, @scale)

debug { @d.line 0.0, y_offset, @raw_columns, y_offset }
end

# Draws the data value over the data point in bar graphs
def draw_value_label(x_offset, y_offset, data_point, bar_value=false)
return if @hide_line_markers && !bar_value

#y_offset = @graph_bottom + LABEL_MARGIN

@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 = NorthGravity
@d = @d.annotate_scaled(@base_image,
1.0, 1.0,
x_offset, y_offset,
data_point.to_s, @scale)

debug { @d.line 0.0, y_offset, @raw_columns, y_offset }
end

# Shows an error message because you have no data.
def draw_no_data
Expand Down Expand Up @@ -1081,3 +1132,10 @@ def annotate_scaled(img, width, height, x, y, text, scale)
end

end # Magick

class String
#Taken from http://codesnippets.joyent.com/posts/show/330
def commify(delimiter=",")
return self.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
end
end
22 changes: 17 additions & 5 deletions lib/gruff/side_bar.rb
Expand Up @@ -57,8 +57,18 @@ def draw_bars
@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)
draw_label(label_center, point_index)

if @use_data_label
label_center = @graph_top + (@bar_width * (row_index+point_index) + @bar_width / 2)
draw_label(label_center, row_index, @norm_data[row_index][DATA_LABEL_INDEX])
else
label_center = @graph_top + (@bars_width * point_index + @bars_width / 2)
draw_label(label_center, point_index)
end
if @show_labels_for_bar_values
val = (@label_formatting || "%.2f") % @norm_data[row_index][3][point_index]
draw_value_label(right_x+40, (@graph_top + (((row_index+point_index+1) * @bar_width) - (@bar_width / 2)))-12, val.commify, true)
end
end

end
Expand All @@ -76,7 +86,8 @@ def draw_line_markers
# Draw horizontal line markers and annotate with numbers
@d = @d.stroke(@marker_color)
@d = @d.stroke_width 1
number_of_lines = 5
number_of_lines = @marker_count || 5
number_of_lines = 1 if number_of_lines == 0

# TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
increment = significant(@spread.to_f / number_of_lines)
Expand Down Expand Up @@ -107,8 +118,9 @@ def draw_line_markers
##
# Draw on the Y axis instead of the X

def draw_label(y_offset, index)
def draw_label(y_offset, index, label=nil)
if !@labels[index].nil? && @labels_seen[index].nil?
lbl = (@use_data_label) ? label : @labels[index]
@d.fill = @font_color
@d.font = @font if @font
@d.stroke = 'transparent'
Expand All @@ -118,7 +130,7 @@ def draw_label(y_offset, index)
@d = @d.annotate_scaled(@base_image,
1, 1,
-@graph_left + LABEL_MARGIN * 2.0, y_offset,
@labels[index], @scale)
lbl, @scale)
@labels_seen[index] = 1
end
end
Expand Down
20 changes: 17 additions & 3 deletions lib/gruff/side_stacked_bar.rb
Expand Up @@ -33,7 +33,10 @@ def draw_bars
height = Array.new(@column_count, 0)
length = Array.new(@column_count, @graph_left)
padding = (@bar_width * (1 - @bar_spacing)) / 2

if @show_labels_for_bar_values
label_values = Array.new
0.upto(@column_count-1) {|i| label_values[i] = {:value => 0, :right_x => 0}}
end
@norm_data.each_with_index do |data_row, row_index|
data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|

Expand All @@ -53,7 +56,12 @@ def draw_bars
right_y = left_y + @bar_width * @bar_spacing
length[point_index] += difference
height[point_index] += (data_point * @graph_width - 2)


if @show_labels_for_bar_values
label_values[point_index][:value] += @norm_data[row_index][3][point_index]
label_values[point_index][:right_x] = right_x
end

# if a data point is 0 it can result in weird really thing lines
# that shouldn't even be there being drawn on top of the existing
# bar - this is bad
Expand All @@ -68,7 +76,13 @@ def draw_bars
end

end

if @show_labels_for_bar_values
label_values.each_with_index do |data, i|
val = (@label_formatting || "%.2f") % data[:value]
draw_value_label(data[:right_x]+40, (@graph_top + (((i+1) * @bar_width) - (@bar_width / 2)))-12, val.commify, true)
end
end

@d.draw(@base_image)
end

Expand Down
1 change: 1 addition & 0 deletions test/gruff_test_case.rb
Expand Up @@ -124,6 +124,7 @@ def setup_basic_graph(*args)
g = klass.new(size)
g.title = "My Bar Graph"
g.labels = @labels
g.font = "/Library/Fonts/Verdana.ttf"


@datasets.each do |data|
Expand Down
12 changes: 12 additions & 0 deletions test/test_bar.rb
Expand Up @@ -444,6 +444,18 @@ def test_set_label_max_size_and_label_truncation_style
g.write("test/output/bar_set_trailing_dots_trunc.png")
end

def test_bar_value_labels
g = setup_basic_graph
g.show_labels_for_bar_values = true
g.write("test/output/bar_value_labels.png")
end

def test_zero_marker_count
g = setup_basic_graph
g.marker_count = 0
g.write("test/output/bar_zero_marker_count.png")
end

protected

def setup_basic_graph(size=800)
Expand Down
13 changes: 13 additions & 0 deletions test/test_side_bar.rb
Expand Up @@ -38,6 +38,19 @@ def test_x_axis_range
g.labels = {0 => '2003', 2 => '2004', 4 => '2005'}
g.write("test/output/side_bar_data_range.png")
end

def test_bar_labels
g = Gruff::SideBar.new('400x300')
g.title = 'Should show labels for each bar'
g.data("Grapes", [8])
g.data("Apples", [24])
g.data("Oranges", [32])
g.data("Watermelon", [8])
g.data("Peaches", [12])
g.labels = {0 => '2003', 2 => '2004', 4 => '2005'}
g.show_labels_for_bar_values = true
g.write("test/output/side_bar_labels.png")
end

end

16 changes: 16 additions & 0 deletions test/test_sidestacked_bar.rb
Expand Up @@ -72,6 +72,22 @@ def test_should_space_long_left_labels_appropriately
end
g.write "test/output/side_stacked_bar_long_label.png"
end

def test_bar_labels
g = Gruff::SideStackedBar.new
g.title = "Stacked Bar Long Label"
g.labels = {
0 => 'September',
1 => 'Oct',
2 => 'Nov',
3 => 'Dec',
}
@datasets.each do |data|
g.data(data[0], data[1])
end
g.show_labels_for_bar_values = true
g.write "test/output/side_stacked_bar_labels.png"
end

protected

Expand Down

0 comments on commit cf1e090

Please sign in to comment.