diff --git a/README.md b/README.md index 94c706a2..9ecba502 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ v0.7.1b: fix pre normalize for secondary y axis +v0.7.2: +- add `x_axis_on_top`, if true, x axis markers will be drawn on top instead of bottom +- fix `marker_format` not working for `side bar` chart + # Gruff Graphs [![Build Status](https://travis-ci.org/topfunky/gruff.svg?branch=master)](https://travis-ci.org/topfunky/gruff) diff --git a/lib/gruff/base.rb b/lib/gruff/base.rb index 3e6baaf9..0278a720 100644 --- a/lib/gruff/base.rb +++ b/lib/gruff/base.rb @@ -225,6 +225,9 @@ class Base # Data for the secondary y axis attr_reader :right_y_axis + # flag to draw x-axis on top instead of bottom, default: false + attr_accessor :x_axis_on_top + # 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.). @@ -312,6 +315,7 @@ def initialize_ivars @norm_data = nil @right_y_axis = nil + @x_axis_on_top = false end # Sets the top, bottom, left and right margins to +margin+. @@ -588,6 +592,8 @@ def setup_graph_measurements @graph_right_margin, @graph_bottom_margin) = [@left_margin, @right_margin, @bottom_margin] else + graph_top_margin = 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 @@ -629,8 +635,12 @@ def setup_graph_measurements 0 @graph_right_margin = @right_margin + extra_room_for_long_label + rline_number_width + (!@right_y_axis.nil? && !@right_y_axis.label.nil? ? @marker_caps_height : 0.0) - @graph_bottom_margin = @bottom_margin + - @marker_caps_height + LABEL_MARGIN + @graph_bottom_margin = @bottom_margin + if @x_axis_on_top + graph_top_margin = @marker_caps_height + LABEL_MARGIN + else + @graph_bottom_margin += @marker_caps_height + LABEL_MARGIN + end end @graph_right = @raw_columns - @graph_right_margin @@ -650,7 +660,13 @@ def setup_graph_measurements x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN # FIXME: Consider chart types other than bar - @graph_bottom += @raw_rows - @graph_bottom_margin - x_axis_label_height - @label_stagger_height + if @x_axis_on_top + puts x_axis_label_height + @graph_top += graph_top_margin + x_axis_label_height + else + @graph_bottom -= x_axis_label_height + end + @graph_bottom += @raw_rows - @graph_bottom_margin - @label_stagger_height @graph_height = @graph_bottom - @graph_top end @@ -660,7 +676,11 @@ def draw_axis_labels # X Axis # Centered vertically and horizontally by setting the # height to 1.0 and the width to the width of the graph. - x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN * 2 + @marker_caps_height + if @x_axis_on_top + x_axis_label_y_coordinate = @graph_top + else + x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN * 2 + @marker_caps_height + end # TODO Center between graph area @d.fill = @font_color @@ -909,7 +929,11 @@ def draw_legend current_x_offset = center(sum(label_widths.first)) # x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN * 2 + @marker_caps_height if @legend_at_bottom - current_y_offset = @graph_bottom + LABEL_MARGIN * 2 + @marker_caps_height + @legend_caps_height + if @x_axis_on_top + current_y_offset = @graph_bottom + LABEL_MARGIN * 2 + @legend_caps_height + else + current_y_offset = @graph_bottom + LABEL_MARGIN * 2 + @marker_caps_height + @legend_caps_height + end else current_y_offset = @legend_at_bottom ? @graph_height + title_margin : (@hide_title ? @top_margin + title_margin : @@ -993,7 +1017,11 @@ def draw_label(x_offset, index) return if @hide_line_markers if !@labels[index].nil? && @labels_seen[index].nil? - y_offset = @graph_bottom + LABEL_MARGIN + if @x_axis_on_top + y_offset = @graph_top - @marker_caps_height - LABEL_MARGIN + else + y_offset = @graph_bottom + LABEL_MARGIN + end # TESTME # FIXME: Consider chart types other than bar diff --git a/lib/gruff/side_bar.rb b/lib/gruff/side_bar.rb index d5f88768..9ef62977 100644 --- a/lib/gruff/side_bar.rb +++ b/lib/gruff/side_bar.rb @@ -99,17 +99,23 @@ def draw_line_markers diff = index - number_of_lines marker_label = diff.abs * increment + @minimum_value + if @x_axis_on_top + y = @graph_top - @marker_caps_height - LABEL_MARGIN + else + y = @graph_bottom + LABEL_MARGIN + end + 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 + @d.gravity = NorthGravity # 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) + x, y, # Coordinates of text + label(marker_label.to_s, nil, @marker_format), @scale) end # unless @d = @d.stroke_antialias true end diff --git a/lib/gruff/version.rb b/lib/gruff/version.rb index 364f5a35..734f433a 100644 --- a/lib/gruff/version.rb +++ b/lib/gruff/version.rb @@ -1,3 +1,3 @@ module Gruff - VERSION = '0.7.1b' + VERSION = '0.7.2' end diff --git a/test/output/bar_and_line_top_x_axis.png b/test/output/bar_and_line_top_x_axis.png new file mode 100644 index 00000000..5792c77b Binary files /dev/null and b/test/output/bar_and_line_top_x_axis.png differ diff --git a/test/output/bar_and_line_top_x_axis_right_y.png b/test/output/bar_and_line_top_x_axis_right_y.png new file mode 100644 index 00000000..c3d78c45 Binary files /dev/null and b/test/output/bar_and_line_top_x_axis_right_y.png differ diff --git a/test/output/bar_x_on_top.png b/test/output/bar_x_on_top.png new file mode 100644 index 00000000..0f787471 Binary files /dev/null and b/test/output/bar_x_on_top.png differ diff --git a/test/output/line_x_on_top.png b/test/output/line_x_on_top.png new file mode 100644 index 00000000..a65dba93 Binary files /dev/null and b/test/output/line_x_on_top.png differ diff --git a/test/output/sidebar_x_on_top.png b/test/output/sidebar_x_on_top.png new file mode 100644 index 00000000..854ba738 Binary files /dev/null and b/test/output/sidebar_x_on_top.png differ diff --git a/test/test_x_axis.rb b/test/test_x_axis.rb new file mode 100644 index 00000000..93ca5f23 --- /dev/null +++ b/test/test_x_axis.rb @@ -0,0 +1,122 @@ +#!/usr/bin/ruby + +require File.dirname(__FILE__) + '/gruff_test_case' + +class TestGruffLine < GruffTestCase + def test_x_axis_on_top + g = setup_basic_graph('800x500') + g.title = 'TOP x axis chart' + g.legend_at_bottom = true + g.x_axis_on_top = true + g.write('test/output/line_x_on_top.png') + end + + def test_side_bar_x_axis_on_top + g = Gruff::SideBar.new('800x400') + g.title = 'TOP X Side Bar Graph' + g.labels = @labels + @datasets.each do |data| + g.data(data[0], data[1][0]) + end + g.minimum_value = 0 + g.maximum_value = 100 + g.bar_spacing = 0.5 + g.hide_legend = true + g.label_formatting = '%.1f%%' + g.marker_format = '%.0f%%' + g.marker_font_size = 15 + g.show_labels_for_bar_values = true + g.top_margin = 0 + g.x_axis_on_top = true + g.write('test/output/sidebar_x_on_top.png') + end + + def test_bar_graph_x_axis_on_top + g = Gruff::Bar.new('400x600') + g.title = 'TOP X Bar Graph' + g.labels = @labels + @datasets.each do |data| + g.data(data[0], data[1]) + end + g.minimum_value = 0 + g.maximum_value = 100 + g.bar_spacing = 0.5 + g.hide_legend = true + g.label_formatting = '%.1f%%' + g.marker_format = '%.0f%%' + g.marker_font_size = 15 + g.show_labels_for_bar_values = true + g.top_margin = 0 + g.x_axis_on_top = true + g.write('test/output/bar_x_on_top.png') + end + + def test_line_bar_x_axis_on_top + @datasets = [ + [:Jimmy, [25, 36, 86, 39]], + [:Charles, [80, 54, 67, 54]], + [:Julie, [22, 29, 35, 38]], + [:Philip, [80, 34, 23, 12]] + #[: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]], + ] + + g = Gruff::BarNLine.new(800) + g.title = 'Bar and Line (50% space)' + g.labels = { + 0 => '5/6', + 1 => '5/15', + 2 => '5/24', + 3 => '5/30', + } + @datasets.each_with_index do |data, idx| + if idx > 1 + g.data_line(data[0], data[1]) + next + end + g.data(data[0], data[1]) + end + g.bar_spacing = 0.5 + g.data_column_spacing = 0.5 + g.minimum_value = 0 + g.x_axis_on_top = true + + g.write('test/output/bar_and_line_top_x_axis.png') + + + g = Gruff::BarNLine.new(800) + g.title = 'Bar and Line (right Y)' + + g.labels = { + 0 => '5/6', + 1 => '5/15', + 2 => '5/24', + 3 => '5/30', + } + @datasets.each_with_index do |data, idx| + if idx > 1 + g.data_line(data[0], data[1]) + next + end + g.data(data[0], data[1]) + end + g.minimum_value = 0 + + g.right_y_axis = Gruff::Axis.new + g.right_y_axis.label = 'the perc' + g.right_y_axis.label_color = 'yellow' + g.right_y_axis.line_color = 'grey' + g.right_y_axis.maximum_value = 100 + g.right_y_axis.minimum_value = 0 + g.right_y_axis.format = '%.0f%%' + g.right_y_axis.skip_lines = [0] + g.right_y_axis.count = 5 + g.right_y_axis.stroke_dash = [3, 5] + g.right_y_axis.stroke_opacity = 0.4 + g.x_axis_on_top = true + + g.write('test/output/bar_and_line_top_x_axis_right_y.png') + end + +end