gruff 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/gruff/bullet.rb CHANGED
@@ -67,23 +67,23 @@ class Gruff::Bullet < Gruff::Base
67
67
  %i[high low].each_with_index do |indicator, index|
68
68
  next unless @options.key?(indicator)
69
69
 
70
- indicator_width_x = graph_left + graph_width * (@options[indicator] / maximum_value)
70
+ indicator_width_x = graph_left + (graph_width * (@options[indicator] / maximum_value))
71
71
 
72
72
  rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @colors[index + 1])
73
73
  rect_renderer.render(graph_left, 0, indicator_width_x, graph_height)
74
74
  end
75
75
 
76
76
  if @options.key?(:target)
77
- target_x = graph_left + graph_width * (@options[:target] / maximum_value)
77
+ target_x = graph_left + (graph_width * (@options[:target] / maximum_value))
78
78
  half_thickness = thickness / 2.0
79
79
 
80
80
  rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @marker_color)
81
- rect_renderer.render(target_x, half_thickness, target_x + half_thickness, thickness * 2 + half_thickness)
81
+ rect_renderer.render(target_x, half_thickness, target_x + half_thickness, (thickness * 2) + half_thickness)
82
82
  end
83
83
 
84
84
  # Value
85
85
  rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @marker_color)
86
- rect_renderer.render(graph_left, thickness, graph_left + graph_width * (@value / maximum_value), thickness * 2)
86
+ rect_renderer.render(graph_left, thickness, graph_left + (graph_width * (@value / maximum_value)), thickness * 2)
87
87
  end
88
88
 
89
89
  private
@@ -94,6 +94,6 @@ private
94
94
  font_height = calculate_caps_height(@title_font)
95
95
 
96
96
  text_renderer = Gruff::Renderer::Text.new(renderer, @title, font: @title_font)
97
- text_renderer.add_to_render_queue(1.0, 1.0, font_height / 2, font_height / 2, Magick::NorthWestGravity)
97
+ text_renderer.add_to_render_queue(1.0, 1.0, font_height / 2.0, font_height / 2.0, Magick::NorthWestGravity)
98
98
  end
99
99
  end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Here's how to set up a Gruff::Candlestick.
5
+ #
6
+ # g = Gruff::Candlestick.new
7
+ # g.data low: 79.30, high: 93.10, open: 79.44, close: 91.20
8
+ # g.data low: 89.14, high: 106.42, open: 91.28, close: 106.26
9
+ # g.data low: 107.89, high: 131.00, open: 108.20, close: 129.04
10
+ # g.data low: 103.10, high: 137.98, open: 132.76, close: 115.81
11
+ # g.write("candlestick.png")
12
+ #
13
+ class Gruff::Candlestick < Gruff::Base
14
+ # Allow for vertical marker lines.
15
+ attr_writer :show_vertical_markers
16
+
17
+ # Specifies the filling opacity in area graph. Default is +0.4+.
18
+ attr_writer :fill_opacity
19
+
20
+ # Specifies the stroke width in line. Default is +2.0+.
21
+ attr_writer :stroke_width
22
+
23
+ # Specifies the color with up bar. Default is +'#579773'+.
24
+ attr_writer :up_color
25
+
26
+ # Specifies the color with down bar. Default is +'#eb5242'+.
27
+ attr_writer :down_color
28
+
29
+ # Can be used to adjust the spaces between the bars.
30
+ # Accepts values between 0.00 and 1.00 where 0.00 means no spacing at all
31
+ # and 1 means that each bars' width is nearly 0 (so each bar is a simple
32
+ # line with no x dimension).
33
+ #
34
+ # Default value is +0.9+.
35
+ def spacing_factor=(space_percent)
36
+ raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' unless (space_percent >= 0) && (space_percent <= 1)
37
+
38
+ @spacing_factor = (1 - space_percent)
39
+ end
40
+
41
+ def data(low:, high:, open:, close:)
42
+ super('', [low, high, open, close])
43
+ end
44
+
45
+ private
46
+
47
+ def initialize_attributes
48
+ super
49
+ @show_vertical_markers = false
50
+ @fill_opacity = 0.4
51
+ @spacing_factor = 0.9
52
+ @stroke_width = 2.0
53
+ @up_color = '#579773'
54
+ @down_color = '#eb5242'
55
+
56
+ @sort = false
57
+ @hide_legend = true
58
+ end
59
+
60
+ def draw_graph
61
+ # Setup the BarConversion Object
62
+ conversion = Gruff::BarConversion.new(
63
+ top: @graph_top, bottom: @graph_bottom,
64
+ minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
65
+ )
66
+
67
+ width = (@graph_width - calculate_spacing) / normalized_candlesticks.size
68
+ bar_width = width * @spacing_factor
69
+ padding = width - bar_width
70
+
71
+ normalized_candlesticks.each_with_index do |candlestick, index|
72
+ left_x = @graph_left + (width * index) + (padding / 2.0)
73
+ right_x = left_x + bar_width
74
+ center_x = (left_x + right_x) / 2.0
75
+ color = candlestick.close >= candlestick.open ? @up_color : @down_color
76
+
77
+ draw_label(center_x, index) do
78
+ break if @hide_line_markers
79
+ break unless @show_vertical_markers
80
+
81
+ Gruff::Renderer::Line.new(renderer, color: @marker_color).render(center_x, @graph_bottom, center_x, @graph_top)
82
+ if @marker_shadow_color
83
+ Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color)
84
+ .render(center_x + 1, @graph_bottom, center_x + 1, @graph_top)
85
+ end
86
+ end
87
+
88
+ open_y, = conversion.get_top_bottom_scaled(candlestick.open)
89
+ close_y, = conversion.get_top_bottom_scaled(candlestick.close)
90
+ Gruff::Renderer::Rectangle.new(renderer, color: color, opacity: @fill_opacity, width: @stroke_width).render(left_x, open_y, right_x, close_y)
91
+
92
+ low_y, = conversion.get_top_bottom_scaled(candlestick.low)
93
+ y = open_y < close_y ? close_y : open_y
94
+ Gruff::Renderer::Line.new(renderer, color: color, width: @stroke_width).render(center_x, low_y, center_x, y)
95
+ high_y, = conversion.get_top_bottom_scaled(candlestick.high)
96
+ y = open_y > close_y ? close_y : open_y
97
+ Gruff::Renderer::Line.new(renderer, color: color, width: @stroke_width).render(center_x, y, center_x, high_y)
98
+ end
99
+ end
100
+
101
+ def normalized_candlesticks
102
+ @candlesticks ||= store.norm_data.map { |data| Gruff::Candlestick::CandlestickData.new(*data.points) }
103
+ end
104
+
105
+ def calculate_spacing
106
+ @scale * (column_count - 1)
107
+ end
108
+
109
+ # @private
110
+ class CandlestickData < Struct.new(:low, :high, :open, :close)
111
+ end
112
+ end
data/lib/gruff/dot.rb CHANGED
@@ -14,32 +14,32 @@
14
14
  # g.write('dot.png')
15
15
  #
16
16
  class Gruff::Dot < Gruff::Base
17
- private
18
-
19
- def initialize_attributes
17
+ def initialize(*)
20
18
  super
21
19
  @has_left_labels = true
22
20
  end
23
21
 
22
+ private
23
+
24
24
  def draw_graph
25
25
  # Setup spacing.
26
26
  #
27
27
  spacing_factor = 1.0
28
28
 
29
- items_width = @graph_height / column_count.to_f
29
+ items_width = @graph_height / column_count
30
30
  item_width = items_width * spacing_factor / store.length
31
31
  padding = (items_width * (1 - spacing_factor)) / 2
32
32
 
33
33
  store.norm_data.each_with_index do |data_row, row_index|
34
34
  data_row.points.each_with_index do |data_point, point_index|
35
35
  x_pos = @graph_left + (data_point * @graph_width)
36
- y_pos = @graph_top + (items_width * point_index) + padding + (items_width.to_f / 2.0).round
36
+ y_pos = @graph_top + (items_width * point_index) + padding + (items_width / 2.0)
37
37
 
38
38
  if row_index == 0
39
39
  Gruff::Renderer::Line.new(renderer, color: @marker_color).render(@graph_left, y_pos, @graph_left + @graph_width, y_pos)
40
40
  end
41
41
 
42
- Gruff::Renderer::Circle.new(renderer, color: data_row.color).render(x_pos, y_pos, x_pos + (item_width.to_f / 3.0).round, y_pos)
42
+ Gruff::Renderer::Circle.new(renderer, color: data_row.color).render(x_pos, y_pos, x_pos + (item_width / 3.0), y_pos)
43
43
 
44
44
  draw_label(y_pos, point_index)
45
45
  end
@@ -51,11 +51,11 @@ private
51
51
  return if @hide_line_markers
52
52
 
53
53
  (0..marker_count).each do |index|
54
- marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
55
- x = @graph_left + (marker_label - minimum_value) * @graph_width / @spread
54
+ marker_label = (BigDecimal(index.to_s) * BigDecimal(@increment.to_s)) + BigDecimal(minimum_value.to_s)
55
+ x = @graph_left + ((marker_label - minimum_value) * @graph_width / @spread)
56
56
 
57
- line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
58
- line_renderer.render(x, @graph_bottom, x, @graph_bottom + 5)
57
+ Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_bottom + 5)
58
+ Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x, @graph_bottom + 1, x, @graph_bottom + 6) if @marker_shadow_color
59
59
 
60
60
  unless @hide_line_numbers
61
61
  label = y_axis_label(marker_label, @increment)
data/lib/gruff/font.rb CHANGED
@@ -3,7 +3,10 @@
3
3
  # Handle font setting to draw texts
4
4
  class Gruff::Font
5
5
  BOLD_PATH = File.expand_path(File.join(__FILE__, '../../../assets/fonts/Roboto-Bold.ttf')).freeze
6
+ private_constant :BOLD_PATH
7
+
6
8
  REGULAR_PATH = File.expand_path(File.join(__FILE__, '../../../assets/fonts/Roboto-Regular.ttf')).freeze
9
+ private_constant :REGULAR_PATH
7
10
 
8
11
  # Get/set font path.
9
12
  attr_accessor :path
@@ -41,17 +41,17 @@ class Gruff::BarConversion
41
41
  case @mode
42
42
  when 1
43
43
  # minimum value >= 0 ( only positive values )
44
- result[0] = @graph_top + @graph_height * (1 - data_point)
44
+ result[0] = @graph_top + (@graph_height * (1 - data_point))
45
45
  result[1] = @graph_top + @graph_height
46
46
  when 2
47
47
  # only negative values
48
48
  result[0] = @graph_top
49
- result[1] = @graph_top + @graph_height * (1 - data_point)
49
+ result[1] = @graph_top + (@graph_height * (1 - data_point))
50
50
  when 3
51
51
  # positive and negative values
52
- val = data_point - @minimum_value / @spread
53
- result[0] = @graph_top + @graph_height * (1 - (val - @zero))
54
- result[1] = @graph_top + @graph_height * (1 - @zero)
52
+ val = data_point - (@minimum_value / @spread)
53
+ result[0] = @graph_top + (@graph_height * (1 - (val - @zero)))
54
+ result[1] = @graph_top + (@graph_height * (1 - @zero))
55
55
  else
56
56
  result[0] = 0.0
57
57
  result[1] = 0.0
@@ -4,6 +4,20 @@
4
4
  module Gruff::BarValueLabel
5
5
  using String::GruffCommify
6
6
 
7
+ # @private
8
+ def self.metrics(value, format, proc_text_metrics)
9
+ val = begin
10
+ if format.is_a?(Proc)
11
+ format.call(value)
12
+ else
13
+ sprintf(format || '%.2f', value).commify
14
+ end
15
+ end
16
+
17
+ metrics = proc_text_metrics.call(val)
18
+ [val, metrics]
19
+ end
20
+
7
21
  # @private
8
22
  class Base
9
23
  attr_reader :coordinate, :value
@@ -16,34 +30,23 @@ module Gruff::BarValueLabel
16
30
 
17
31
  # @private
18
32
  class Bar < Base
19
- def prepare_rendering(format, _bar_width = 0)
20
- left_x, left_y, right_x, _right_y = @coordinate
21
- val = begin
22
- if format.is_a?(Proc)
23
- format.call(@value)
24
- else
25
- sprintf(format || '%.2f', @value).commify
26
- end
27
- end
33
+ def prepare_rendering(format, proc_text_metrics)
34
+ left_x, left_y, _right_x, _right_y = @coordinate
35
+ val, metrics = Gruff::BarValueLabel.metrics(@value, format, proc_text_metrics)
28
36
 
29
- y = @value >= 0 ? left_y - 30 : left_y + 12
30
- yield left_x + (right_x - left_x) / 2, y, val
37
+ y = @value >= 0 ? left_y - metrics.height - 5 : left_y + 5
38
+ yield left_x, y, val, metrics.width, metrics.height
31
39
  end
32
40
  end
33
41
 
34
42
  # @private
35
43
  class SideBar < Base
36
- def prepare_rendering(format, bar_width = 0)
37
- left_x, _left_y, right_x, right_y = @coordinate
38
- val = begin
39
- if format.is_a?(Proc)
40
- format.call(@value)
41
- else
42
- sprintf(format || '%.2f', @value).commify
43
- end
44
- end
45
- x = @value >= 0 ? right_x + 40 : left_x - 40
46
- yield x, right_y - bar_width / 2, val
44
+ def prepare_rendering(format, proc_text_metrics)
45
+ left_x, left_y, right_x, _right_y = @coordinate
46
+ val, metrics = Gruff::BarValueLabel.metrics(@value, format, proc_text_metrics)
47
+
48
+ x = @value >= 0 ? right_x + 10 : left_x - metrics.width - 10
49
+ yield x, left_y, val, metrics.width, metrics.height
47
50
  end
48
51
  end
49
52
 
@@ -59,12 +62,12 @@ module Gruff::BarValueLabel
59
62
  @bars[index] = bars
60
63
  end
61
64
 
62
- def prepare_rendering(format, bar_width = 0, &block)
65
+ def prepare_rendering(format, proc_text_metrics, &block)
63
66
  @bars.each do |bars|
64
67
  value = bars.sum(&:value)
65
68
  bar = bars.last
66
69
  bar_value_label = bar.class.new(bar.coordinate, value)
67
- bar_value_label.prepare_rendering(format, bar_width, &block)
70
+ bar_value_label.prepare_rendering(format, proc_text_metrics, &block)
68
71
  end
69
72
  end
70
73
  end
@@ -16,7 +16,9 @@ module Gruff::Base::StackedMixin
16
16
 
17
17
  max_hash.each_key do |key|
18
18
  self.maximum_value = max_hash[key] if max_hash[key] > maximum_value
19
+ self.minimum_value = max_hash[key] if max_hash[key] < minimum_value
19
20
  end
20
- self.minimum_value = 0
21
+
22
+ raise "Can't handle negative values in stacked graph" if minimum_value < 0
21
23
  end
22
24
  end
@@ -29,7 +29,7 @@ class Gruff::Histogram < Gruff::Bar
29
29
  end
30
30
 
31
31
  def data(name, data_points = [], color = nil)
32
- @data << [name, data_points, color]
32
+ @data << [name, Array(data_points), color]
33
33
  end
34
34
 
35
35
  private
data/lib/gruff/line.rb CHANGED
@@ -40,6 +40,23 @@ class Gruff::Line < Gruff::Base
40
40
  # The number of vertical lines shown.
41
41
  attr_writer :marker_x_count
42
42
 
43
+ # Call with target pixel width of graph (+800+, +400+, +300+), and/or +false+ to omit lines (points only).
44
+ #
45
+ # g = Gruff::Line.new(400) # 400px wide with lines
46
+ # g = Gruff::Line.new(400, false) # 400px wide, no lines (for backwards compatibility)
47
+ # g = Gruff::Line.new(false) # Defaults to 800px wide, no lines (for backwards compatibility)
48
+ #
49
+ # The preferred way is to call {#hide_dots=} or {#hide_lines=} instead.
50
+ def initialize(*args)
51
+ raise ArgumentError, 'Wrong number of arguments' if args.length > 2
52
+
53
+ if args.empty? || (!args.first.is_a?(Numeric) && !args.first.is_a?(String))
54
+ super()
55
+ else
56
+ super args.shift
57
+ end
58
+ end
59
+
43
60
  # Get the value if somebody has defined it.
44
61
  def baseline_value
45
62
  if @reference_lines.key?(:baseline)
@@ -64,23 +81,6 @@ class Gruff::Line < Gruff::Base
64
81
  @reference_lines[:baseline][:color] = new_value
65
82
  end
66
83
 
67
- # Call with target pixel width of graph (+800+, +400+, +300+), and/or +false+ to omit lines (points only).
68
- #
69
- # g = Gruff::Line.new(400) # 400px wide with lines
70
- # g = Gruff::Line.new(400, false) # 400px wide, no lines (for backwards compatibility)
71
- # g = Gruff::Line.new(false) # Defaults to 800px wide, no lines (for backwards compatibility)
72
- #
73
- # The preferred way is to call {#hide_dots=} or {#hide_lines=} instead.
74
- def initialize(*args)
75
- raise ArgumentError, 'Wrong number of arguments' if args.length > 2
76
-
77
- if args.empty? || (!args.first.is_a?(Numeric) && !args.first.is_a?(String))
78
- super()
79
- else
80
- super args.shift
81
- end
82
- end
83
-
84
84
  # This method allows one to plot a dataset with both X and Y data.
85
85
  #
86
86
  # @overload dataxy(name, x_data_points = [], y_data_points = [], color = nil)
@@ -165,7 +165,7 @@ private
165
165
  end
166
166
 
167
167
  def draw_horizontal_reference_line(reference_line)
168
- level = @graph_top + (@graph_height - reference_line[:norm_value] * @graph_height)
168
+ level = @graph_top + (@graph_height - (reference_line[:norm_value] * @graph_height))
169
169
  draw_reference_line(reference_line, @graph_left, @graph_left + @graph_width, level, level)
170
170
  end
171
171
 
@@ -176,7 +176,7 @@ private
176
176
 
177
177
  def draw_graph
178
178
  # Check to see if more than one datapoint was given. NaN can result otherwise.
179
- @x_increment = column_count > 1 ? (@graph_width / (column_count - 1).to_f) : @graph_width
179
+ @x_increment = column_count > 1 ? @graph_width / (column_count - 1) : @graph_width
180
180
 
181
181
  @reference_lines.each_value do |curr_reference_line|
182
182
  draw_horizontal_reference_line(curr_reference_line) if curr_reference_line.key?(:norm_value)
@@ -189,22 +189,22 @@ private
189
189
  one_point = contains_one_point_only?(data_row)
190
190
 
191
191
  data_row.coordinates.each_with_index do |(x_data, y_data), index|
192
- if x_data.nil?
193
- # use the old method: equally spaced points along the x-axis
194
- new_x = @graph_left + (@x_increment * index)
195
- draw_label(new_x, index)
196
- else
197
- new_x = get_x_coord(x_data, @graph_width, @graph_left)
198
- @labels.each do |label_pos, _|
199
- draw_label(@graph_left + ((label_pos - @minimum_x_value) * @graph_width) / (@maximum_x_value - @minimum_x_value), label_pos)
192
+ new_x = begin
193
+ if x_data.nil?
194
+ # use the old method: equally spaced points along the x-axis
195
+ @graph_left + (@x_increment * index)
196
+ else
197
+ get_x_coord(x_data, @graph_width, @graph_left)
200
198
  end
201
199
  end
200
+ draw_label_for_x_data(x_data, new_x, index)
201
+
202
202
  unless y_data # we can't draw a line for a null data point, we can still label the axis though
203
203
  prev_x = prev_y = nil
204
204
  next
205
205
  end
206
206
 
207
- new_y = @graph_top + (@graph_height - y_data * @graph_height)
207
+ new_y = @graph_top + (@graph_height - (y_data * @graph_height))
208
208
 
209
209
  # Reset each time to avoid thin-line errors
210
210
  stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 4), 5.0)
@@ -227,12 +227,12 @@ private
227
227
 
228
228
  def setup_data
229
229
  # Update the global min/max values for the x data
230
- @maximum_x_value ||= store.max_x
231
- @minimum_x_value ||= store.min_x
230
+ @maximum_x_value = (@maximum_x_value || store.max_x).to_f
231
+ @minimum_x_value = (@minimum_x_value || store.min_x).to_f
232
232
 
233
233
  # Deal with horizontal reference line values that exceed the existing minimum & maximum values.
234
- possible_maximums = [maximum_value.to_f]
235
- possible_minimums = [minimum_value.to_f]
234
+ possible_maximums = [maximum_value]
235
+ possible_minimums = [minimum_value]
236
236
 
237
237
  @reference_lines.each_value do |curr_reference_line|
238
238
  if curr_reference_line.key?(:value)
@@ -255,14 +255,14 @@ private
255
255
  def normalize
256
256
  return unless data_given?
257
257
 
258
- spread_x = @maximum_x_value.to_f - @minimum_x_value.to_f
258
+ spread_x = @maximum_x_value - @minimum_x_value
259
259
  store.normalize(minimum_x: @minimum_x_value, spread_x: spread_x, minimum_y: minimum_value, spread_y: @spread)
260
260
 
261
261
  @reference_lines.each_value do |curr_reference_line|
262
262
  # We only care about horizontal markers ... for normalization.
263
263
  # Vertical markers won't have a :value, they will have an :index
264
264
 
265
- curr_reference_line[:norm_value] = ((curr_reference_line[:value].to_f - minimum_value) / @spread.to_f) if curr_reference_line.key?(:value)
265
+ curr_reference_line[:norm_value] = ((curr_reference_line[:value].to_f - minimum_value) / @spread) if curr_reference_line.key?(:value)
266
266
  end
267
267
  end
268
268
 
@@ -270,22 +270,28 @@ private
270
270
  # do all of the stuff for the horizontal lines on the y-axis
271
271
  super
272
272
  return if @hide_line_markers
273
+ return unless @show_vertical_markers
273
274
 
274
275
  (0..@marker_x_count).each do |index|
275
- if @show_vertical_markers
276
- x = @graph_left + @graph_width - index * @graph_width / @marker_x_count
276
+ x = @graph_left + @graph_width - (index * @graph_width / @marker_x_count)
277
277
 
278
- Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
279
- # If the user specified a marker shadow color, draw a shadow just below it
280
- if @marker_shadow_color
281
- Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x + 1, @graph_bottom, x + 1, @graph_top)
282
- end
278
+ Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
279
+ Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x + 1, @graph_bottom, x + 1, @graph_top) if @marker_shadow_color
280
+ end
281
+ end
282
+
283
+ def draw_label_for_x_data(x_data, new_x, index)
284
+ if x_data.nil?
285
+ draw_label(new_x, index)
286
+ else
287
+ @labels.each do |label_pos, _|
288
+ draw_label(@graph_left + (((label_pos - @minimum_x_value) * @graph_width) / (@maximum_x_value - @minimum_x_value)), label_pos)
283
289
  end
284
290
  end
285
291
  end
286
292
 
287
293
  def get_x_coord(x_data_point, width, offset)
288
- x_data_point * width + offset
294
+ (x_data_point * width) + offset
289
295
  end
290
296
 
291
297
  def contains_one_point_only?(data_row)
@@ -21,7 +21,7 @@ module Gruff
21
21
 
22
22
  @legend_labels = store.data.map(&:label)
23
23
 
24
- legend_height = scale_fontsize(store.length * calculate_line_height + @top_margin + @bottom_margin)
24
+ legend_height = scale_fontsize((store.length * calculate_line_height) + @top_margin + @bottom_margin)
25
25
 
26
26
  @original_rows = @raw_rows
27
27
  @original_columns = @raw_columns
@@ -45,7 +45,7 @@ module Gruff
45
45
 
46
46
  def calculate_legend_width
47
47
  width = @legend_labels.map { |label| calculate_width(@legend_font, label) }.max
48
- scale_fontsize(width + 40 * 1.7)
48
+ scale_fontsize(width + (40 * 1.7))
49
49
  end
50
50
 
51
51
  ##
@@ -77,9 +77,9 @@ module Gruff
77
77
  # Now draw box with color of this dataset
78
78
  rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
79
79
  rect_renderer.render(current_x_offset,
80
- current_y_offset - legend_square_width / 2.0,
80
+ current_y_offset - (legend_square_width / 2.0),
81
81
  current_x_offset + legend_square_width,
82
- current_y_offset + legend_square_width / 2.0)
82
+ current_y_offset + (legend_square_width / 2.0))
83
83
 
84
84
  current_y_offset += calculate_line_height
85
85
  end
data/lib/gruff/net.rb CHANGED
@@ -50,15 +50,15 @@ private
50
50
 
51
51
  rad_pos = index * Math::PI * 2 / column_count
52
52
  point_distance = data_point * @radius
53
- start_x = @center_x + Math.sin(rad_pos) * point_distance
54
- start_y = @center_y - Math.cos(rad_pos) * point_distance
53
+ start_x = @center_x + (Math.sin(rad_pos) * point_distance)
54
+ start_y = @center_y - (Math.cos(rad_pos) * point_distance)
55
55
 
56
56
  next_index = index + 1 < data_row.points.length ? index + 1 : 0
57
57
 
58
58
  next_rad_pos = next_index * Math::PI * 2 / column_count
59
59
  next_point_distance = data_row.points[next_index] * @radius
60
- end_x = @center_x + Math.sin(next_rad_pos) * next_point_distance
61
- end_y = @center_y - Math.cos(next_rad_pos) * next_point_distance
60
+ end_x = @center_x + (Math.sin(next_rad_pos) * next_point_distance)
61
+ end_y = @center_y - (Math.cos(next_rad_pos) * next_point_distance)
62
62
 
63
63
  Gruff::Renderer::Line.new(renderer, color: data_row.color, width: @stroke_width).render(start_x, start_y, end_x, end_y)
64
64
 
@@ -89,7 +89,7 @@ private
89
89
  rad_pos = index * Math::PI * 2 / column_count
90
90
 
91
91
  Gruff::Renderer::Line.new(renderer, color: @marker_color)
92
- .render(@center_x, @center_y, @center_x + Math.sin(rad_pos) * @radius, @center_y - Math.cos(rad_pos) * @radius)
92
+ .render(@center_x, @center_y, @center_x + (Math.sin(rad_pos) * @radius), @center_y - (Math.cos(rad_pos) * @radius))
93
93
 
94
94
  marker_label = @labels[index] ? @labels[index].to_s : '000'
95
95
  draw_label(@center_x, @center_y, rad_pos * 360 / (2 * Math::PI), @radius + @circle_radius, marker_label)
@@ -99,8 +99,8 @@ private
99
99
  def draw_label(center_x, center_y, angle, radius, amount)
100
100
  x_offset = center_x # + 15 # The label points need to be tweaked slightly
101
101
  y_offset = center_y # + 0 # This one doesn't though
102
- x = x_offset + (radius + LABEL_MARGIN) * Math.sin(deg2rad(angle))
103
- y = y_offset - (radius + LABEL_MARGIN) * Math.cos(deg2rad(angle))
102
+ x = x_offset + ((radius + LABEL_MARGIN) * Math.sin(deg2rad(angle)))
103
+ y = y_offset - ((radius + LABEL_MARGIN) * Math.cos(deg2rad(angle)))
104
104
 
105
105
  draw_label_at(1.0, 1.0, x, y, amount, Magick::CenterGravity)
106
106
  end
@@ -3,6 +3,7 @@
3
3
  # @private
4
4
  module String::GruffCommify
5
5
  THOUSAND_SEPARATOR = ','
6
+ private_constant :THOUSAND_SEPARATOR
6
7
 
7
8
  refine String do
8
9
  # Taken from http://codesnippets.joyent.com/posts/show/330
data/lib/gruff/pie.rb CHANGED
@@ -9,14 +9,14 @@
9
9
  # g.data 'Hamburgers', 50
10
10
  # g.write("pie_keynote.png")
11
11
  #
12
- # To control where the pie chart starts creating slices, use {#zero_degree=}.
12
+ # To control where the pie chart starts creating slices, use {#start_degree=}.
13
13
  #
14
14
  class Gruff::Pie < Gruff::Base
15
- DEFAULT_TEXT_OFFSET_PERCENTAGE = 0.15
15
+ DEFAULT_TEXT_OFFSET_PERCENTAGE = 0.1
16
16
 
17
17
  # Can be used to make the pie start cutting slices at the top (-90.0)
18
- # or at another angle. Default is +0.0+, which starts at 3 o'clock.
19
- attr_writer :zero_degree
18
+ # or at another angle. Default is +-90.0+, which starts at 3 o'clock.
19
+ attr_writer :start_degree
20
20
 
21
21
  # Set the number output format lambda.
22
22
  attr_writer :label_formatting
@@ -26,25 +26,34 @@ class Gruff::Pie < Gruff::Base
26
26
  attr_writer :hide_labels_less_than
27
27
 
28
28
  # Affect the distance between the percentages and the pie chart.
29
- # Defaults to +0.15+.
29
+ # Defaults to +0.1+.
30
30
  attr_writer :text_offset_percentage
31
31
 
32
32
  ## Use values instead of percentages.
33
33
  attr_writer :show_values_as_labels
34
34
 
35
- private
35
+ # Set to +true+ if you want the data sets sorted with largest avg values drawn
36
+ # first. Default is +true+.
37
+ attr_writer :sort
36
38
 
37
- def initialize_store
38
- @store = Gruff::Store.new(Gruff::Store::CustomData)
39
+ # Can be used to make the pie start cutting slices at the top (-90.0)
40
+ # or at another angle. Default is +-90.0+, which starts at 3 o'clock.
41
+ # @deprecated Please use +start_degree+ attribute instead.
42
+ def zero_degree=(value)
43
+ warn '#zero_degree= is deprecated. Please use `start_degree` attribute instead'
44
+ @start_degree = value
39
45
  end
40
46
 
47
+ private
48
+
41
49
  def initialize_attributes
42
50
  super
43
- @zero_degree = 0.0
51
+ @start_degree = -90.0
44
52
  @hide_labels_less_than = 0.0
45
53
  @text_offset_percentage = DEFAULT_TEXT_OFFSET_PERCENTAGE
46
54
  @show_values_as_labels = false
47
55
  @marker_font.bold = true
56
+ @sort = true
48
57
 
49
58
  @hide_line_markers = true
50
59
  @hide_line_markers.freeze
@@ -83,7 +92,7 @@ private
83
92
  # Spatial Value-Related Methods
84
93
 
85
94
  def chart_degrees
86
- @chart_degrees ||= @zero_degree
95
+ @chart_degrees ||= @start_degree
87
96
  end
88
97
 
89
98
  attr_reader :graph_height
@@ -132,7 +141,7 @@ private
132
141
  end
133
142
 
134
143
  def label_coordinates_for(slice)
135
- angle = chart_degrees + slice.degrees / 2
144
+ angle = chart_degrees + (slice.degrees / 2.0)
136
145
 
137
146
  [x_label_coordinate(angle), y_label_coordinate(angle)]
138
147
  end