diff --git a/examples/squid/col_max_width.rb b/examples/squid/col_max_width.rb new file mode 100644 index 0000000..da4c20f --- /dev/null +++ b/examples/squid/col_max_width.rb @@ -0,0 +1,9 @@ +# By default, chart maximizes the width of columns. +# +# You can use the :col_max_width option to limit the maximum width of columns in the chart (measured in points; 72 points per inch). +# +filename = File.basename(__FILE__).gsub('.rb', '.pdf') +Prawn::ManualBuilder::Example.generate(filename) do + data = {views: {2013 => 182, 2014 => 46, 2015 => 134}} + chart data, col_max_width: 20 +end diff --git a/examples/squid/squid.rb b/examples/squid/squid.rb index d8f7a50..bfb112f 100644 --- a/examples/squid/squid.rb +++ b/examples/squid/squid.rb @@ -17,6 +17,7 @@ p.section 'Basics' do |s| s.example 'basic' s.example 'legend' + s.example 'col_max_width' end p.section 'Chart types' do |s| diff --git a/lib/squid/configuration.rb b/lib/squid/configuration.rb index 431af18..3a633c2 100644 --- a/lib/squid/configuration.rb +++ b/lib/squid/configuration.rb @@ -59,6 +59,7 @@ def self.array(proc = nil) labels: {as: array(boolean)}, legend: {as: boolean, default: 'true'}, line_widths: {as: array(float)}, + col_max_width: {as: integer, default: '0'}, steps: {as: integer, default: '4'}, ticks: {as: boolean, default: 'true'}, type: {as: symbol, default: 'column'}, diff --git a/lib/squid/graph.rb b/lib/squid/graph.rb index cf0bb7e..f613f14 100644 --- a/lib/squid/graph.rb +++ b/lib/squid/graph.rb @@ -13,11 +13,11 @@ module Squid class Graph extend Settings has_settings :baseline, :border, :chart, :colors, :every, :formats, :height - has_settings :legend, :line_widths, :steps, :ticks, :type, :labels + has_settings :legend, :line_widths, :col_max_width, :steps, :ticks, :type, :labels def initialize(document, data = {}, settings = {}) @data, @settings = data, settings - @plot = Plotter.new document, bottom: bottom + @plot = Plotter.new document, bottom: bottom, col_max_width: settings[:col_max_width] @plot.paddings = {left: left.width, right: right.width} if @data.any? end diff --git a/lib/squid/plotter.rb b/lib/squid/plotter.rb index be32d42..040d7f3 100644 --- a/lib/squid/plotter.rb +++ b/lib/squid/plotter.rb @@ -7,9 +7,10 @@ module Squid class Plotter attr_accessor :paddings # @param [Prawn::Document] a PDF document to wrap in a Plotter instance. - def initialize(pdf, bottom:) + def initialize(pdf, bottom:, col_max_width: 0) @pdf = pdf @bottom = bottom + @col_max_width = col_max_width || 0 end # Draws a bounding box of the given height, rendering the block inside it. @@ -96,7 +97,12 @@ def lines(series, options = {}) def stacks(series, options = {}) items(series, options.merge(fill: true)) do |point, w, i, padding| x, y = point.index*w + padding + left, point.y + @bottom - @pdf.fill_rectangle [x, y], w - 2*padding, point.height + w -= 2 * padding + if @col_max_width > 0 && @col_max_width < w + x += (w - @col_max_width) / 2 + w = @col_max_width + end + @pdf.fill_rectangle [x, y], w, point.height end end @@ -104,6 +110,10 @@ def columns(series, options = {}) items(series, options.merge(fill: true, count: series.size)) do |point, w, i, padding| item_w = (w - 2 * padding)/ series.size x, y = point.index*w + padding + left + i*item_w, point.y + @bottom + if @col_max_width > 0 && @col_max_width < item_w + x += (item_w - @col_max_width) / 2 + item_w = @col_max_width + end @pdf.fill_rectangle [x, y], item_w, point.height end end diff --git a/spec/configuration_spec.rb b/spec/configuration_spec.rb index 79ca0c2..4490cba 100644 --- a/spec/configuration_spec.rb +++ b/spec/configuration_spec.rb @@ -28,6 +28,7 @@ it_behaves_like 'a configurable setting', method: 'labels', env: 'SQUID_LABELS', default: [], sample_value: sample_true it_behaves_like 'a configurable setting', method: 'legend', env: 'SQUID_LEGEND', default: true, sample_value: sample_false it_behaves_like 'a configurable setting', method: 'line_widths', env: 'SQUID_LINE_WIDTHS', default: [] , sample_value: '4' + it_behaves_like 'a configurable setting', method: 'col_max_width', env: 'SQUID_COL_MAX_WIDTH', default: 0, sample_value: '20' it_behaves_like 'a configurable setting', method: 'steps', env: 'SQUID_STEPS', default: 4, sample_value: '0' it_behaves_like 'a configurable setting', method: 'ticks', env: 'SQUID_TICKS', default: true, sample_value: sample_false it_behaves_like 'a configurable setting', method: 'type', env: 'SQUID_TYPE', default: :column, sample_value: 'line' diff --git a/spec/squid_spec.rb b/spec/squid_spec.rb index 6a7dccf..353538e 100644 --- a/spec/squid_spec.rb +++ b/spec/squid_spec.rb @@ -55,6 +55,16 @@ end end + context 'given the :col_max_width is set to a value greater than zero' do + let(:maximum) { 20 } + let(:settings) { options.merge col_max_width: maximum } + + it 'creates the columns within the specified width' do + widths = rectangles_of(chart).map{ |r| r[:width] } + expect(widths[0]).to eq maximum + end + end + context 'given the series has nil values' do let(:values) { {2013 => -50, 2014 => nil, 2015 => 20} } @@ -144,6 +154,16 @@ it 'includes as many stacks as the number of values' do expect(rectangles_of(chart).map{|r| r[:point].first}.uniq.size).to be 3 end + + context 'given the :col_max_width is set to a value greater than zero' do + let(:maximum) { 20 } + let(:settings) { options.merge type: :stack, col_max_width: maximum } + + it 'creates the columns within the specified width' do + widths = rectangles_of(chart).map{ |r| r[:width] } + expect(widths[0]).to eq maximum + end + end end context 'given multiple options are provided' do