gruff 0.16.0-java → 0.19.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +26 -0
  3. data/.github/workflows/ci.yml +9 -6
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +0 -6
  6. data/CHANGELOG.md +32 -0
  7. data/README.md +7 -3
  8. data/gruff.gemspec +2 -4
  9. data/lib/gruff/area.rb +3 -1
  10. data/lib/gruff/bar.rb +26 -24
  11. data/lib/gruff/base.rb +214 -93
  12. data/lib/gruff/bezier.rb +7 -8
  13. data/lib/gruff/{box_plot.rb → box.rb} +12 -6
  14. data/lib/gruff/bubble.rb +99 -0
  15. data/lib/gruff/candlestick.rb +22 -14
  16. data/lib/gruff/dot.rb +5 -6
  17. data/lib/gruff/helper/bar_conversion.rb +1 -5
  18. data/lib/gruff/helper/bar_mixin.rb +25 -0
  19. data/lib/gruff/helper/bar_value_label.rb +0 -22
  20. data/lib/gruff/helper/stacked_mixin.rb +16 -0
  21. data/lib/gruff/histogram.rb +8 -5
  22. data/lib/gruff/line.rb +47 -27
  23. data/lib/gruff/mini/bar.rb +1 -1
  24. data/lib/gruff/mini/legend.rb +13 -9
  25. data/lib/gruff/mini/pie.rb +2 -2
  26. data/lib/gruff/net.rb +26 -13
  27. data/lib/gruff/pie.rb +7 -2
  28. data/lib/gruff/renderer/bezier.rb +1 -1
  29. data/lib/gruff/renderer/circle.rb +5 -3
  30. data/lib/gruff/renderer/dash_line.rb +1 -1
  31. data/lib/gruff/renderer/dot.rb +26 -15
  32. data/lib/gruff/renderer/line.rb +1 -1
  33. data/lib/gruff/renderer/polygon.rb +1 -1
  34. data/lib/gruff/renderer/polyline.rb +4 -2
  35. data/lib/gruff/renderer/renderer.rb +0 -4
  36. data/lib/gruff/renderer/text.rb +7 -1
  37. data/lib/gruff/scatter.rb +52 -55
  38. data/lib/gruff/side_bar.rb +28 -24
  39. data/lib/gruff/side_stacked_bar.rb +36 -41
  40. data/lib/gruff/spider.rb +7 -2
  41. data/lib/gruff/stacked_area.rb +8 -3
  42. data/lib/gruff/stacked_bar.rb +48 -40
  43. data/lib/gruff/store/xy_data.rb +8 -9
  44. data/lib/gruff/store/xy_pointsizes_data.rb +60 -0
  45. data/lib/gruff/version.rb +1 -1
  46. data/lib/gruff.rb +3 -4
  47. metadata +9 -5
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Here's how to set up a Gruff::Bubble.
5
+ #
6
+ # g = Gruff::Bubble.new
7
+ # g.title = 'Bubble plot'
8
+ # g.write('bubble.png')
9
+ #
10
+ class Gruff::Bubble < Gruff::Scatter
11
+ # Specifies the filling opacity in area graph. Default is +0.6+.
12
+ attr_writer :fill_opacity
13
+
14
+ # Specifies the stroke width in line. Default is +1.0+.
15
+ attr_writer :stroke_width
16
+
17
+ # The first parameter is the name of the dataset. The next two are the
18
+ # x and y axis data points contain in their own array in that respective
19
+ # order. The 4th argument represents sizes of points.
20
+ # The final parameter is the color.
21
+ #
22
+ # Can be called multiple times with different datasets for a multi-valued
23
+ # graph.
24
+ #
25
+ # If the color argument is nil, the next color from the default theme will
26
+ # be used.
27
+ #
28
+ # @note If you want to use a preset theme, you must set it before calling {#data}.
29
+ #
30
+ # @param name [String, Symbol] containing the name of the dataset.
31
+ # @param x_data_points [Array] An Array of x-axis data points.
32
+ # @param y_data_points [Array] An Array of y-axis data points.
33
+ # @param point_sizes [Array] An Array of sizes for points.
34
+ # @param color [String] The hex string for the color of the dataset. Defaults to nil.
35
+ #
36
+ # @raise [ArgumentError] Data points contain nil values.
37
+ # This error will get raised if either the x or y axis data points array
38
+ # contains a +nil+ value. The graph will not make an assumption
39
+ # as how to graph +nil+.
40
+ # @raise [ArgumentError] +x_data_points+ is empty.
41
+ # This error is raised when the array for the x-axis points are empty
42
+ # @raise [ArgumentError] +y_data_points+ is empty.
43
+ # This error is raised when the array for the y-axis points are empty.
44
+ # @raise [ArgumentError] +point_sizes+ is empty.
45
+ # This error is raised when the array for the point_sizes are empty
46
+ # @raise [ArgumentError] +x_data_points.length != y_data_points.length+.
47
+ # Error means that the x and y axis point arrays do not match in length.
48
+ # @raise [ArgumentError] +x_data_points.length != point_sizes.length+.
49
+ # Error means that the x and point_sizes arrays do not match in length.
50
+ #
51
+ # @example
52
+ # g = Gruff::Bubble.new
53
+ # g.title = "Bubble Graph"
54
+ # g.data :A, [-1, 19, -4, -23], [-35, 21, 23, -4], [4.5, 1.0, 2.1, 0.9]
55
+ #
56
+ def data(name, x_data_points = [], y_data_points = [], point_sizes = [], color = nil)
57
+ # make sure it's an array
58
+ x_data_points = Array(x_data_points)
59
+ y_data_points = Array(y_data_points)
60
+ point_sizes = Array(point_sizes)
61
+
62
+ raise ArgumentError, 'Data Points contain nil Value!' if x_data_points.include?(nil) || y_data_points.include?(nil)
63
+ raise ArgumentError, 'x_data_points is empty!' if x_data_points.empty?
64
+ raise ArgumentError, 'y_data_points is empty!' if y_data_points.empty?
65
+ raise ArgumentError, 'point_sizes is empty!' if point_sizes.empty?
66
+ raise ArgumentError, 'x_data_points.length != y_data_points.length!' if x_data_points.length != y_data_points.length
67
+ raise ArgumentError, 'x_data_points.length != point_sizes.length!' if x_data_points.length != point_sizes.length
68
+
69
+ store.add(name, x_data_points, y_data_points, point_sizes, color)
70
+ end
71
+
72
+ private
73
+
74
+ def initialize_store
75
+ @store = Gruff::Store.new(Gruff::Store::XYPointsizeData)
76
+ end
77
+
78
+ def initialize_attributes
79
+ super
80
+
81
+ @fill_opacity = 0.6
82
+ @stroke_width = 1.0
83
+ end
84
+
85
+ def draw_graph
86
+ store.norm_data.each do |data_row|
87
+ data_row.coordinate_and_pointsizes.each do |x_value, y_value, point_size|
88
+ next if y_value.nil? || x_value.nil?
89
+
90
+ new_x = @graph_left + (x_value * @graph_width)
91
+ new_y = @graph_bottom - (y_value * @graph_height)
92
+ diameter = @graph_width / (@marker_count * x_increment) * point_size.to_f
93
+
94
+ Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: @stroke_width, opacity: @fill_opacity)
95
+ .render(new_x, new_y, new_x - (diameter / 2.0), new_y)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -38,6 +38,16 @@ class Gruff::Candlestick < Gruff::Base
38
38
  @spacing_factor = (1 - space_percent)
39
39
  end
40
40
 
41
+ # The sort feature is not supported in this graph.
42
+ def sort=(_value)
43
+ raise 'Not support #sort= in Gruff::Candlestick'
44
+ end
45
+
46
+ # The sort feature is not supported in this graph.
47
+ def sorted_drawing=(_value)
48
+ raise 'Not support #sorted_drawing= in Gruff::Candlestick'
49
+ end
50
+
41
51
  def data(low:, high:, open:, close:)
42
52
  super('', [low, high, open, close])
43
53
  end
@@ -53,7 +63,6 @@ private
53
63
  @up_color = '#579773'
54
64
  @down_color = '#eb5242'
55
65
 
56
- @sort = false
57
66
  @hide_legend = true
58
67
  end
59
68
 
@@ -64,7 +73,7 @@ private
64
73
  minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
65
74
  )
66
75
 
67
- width = (@graph_width - calculate_spacing) / normalized_candlesticks.size
76
+ width = (@graph_width - calculate_spacing) / column_count
68
77
  bar_width = width * @spacing_factor
69
78
  padding = width - bar_width
70
79
 
@@ -74,16 +83,7 @@ private
74
83
  center_x = (left_x + right_x) / 2.0
75
84
  color = candlestick.close >= candlestick.open ? @up_color : @down_color
76
85
 
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
86
+ draw_label(center_x, index) { draw_marker_vertical_line(center_x) if show_marker_vertical_line? }
87
87
 
88
88
  open_y, = conversion.get_top_bottom_scaled(candlestick.open)
89
89
  close_y, = conversion.get_top_bottom_scaled(candlestick.close)
@@ -99,11 +99,19 @@ private
99
99
  end
100
100
 
101
101
  def normalized_candlesticks
102
- @candlesticks ||= store.norm_data.map { |data| Gruff::Candlestick::CandlestickData.new(*data.points) }
102
+ @normalized_candlesticks ||= store.norm_data.map { |data| Gruff::Candlestick::CandlestickData.new(*data.points) }
103
+ end
104
+
105
+ def column_count
106
+ normalized_candlesticks.size
103
107
  end
104
108
 
105
109
  def calculate_spacing
106
- @scale * (column_count - 1)
110
+ column_count - 1
111
+ end
112
+
113
+ def show_marker_vertical_line?
114
+ !@hide_line_markers && @show_vertical_markers
107
115
  end
108
116
 
109
117
  # @private
data/lib/gruff/dot.rb CHANGED
@@ -17,6 +17,7 @@ class Gruff::Dot < Gruff::Base
17
17
  def initialize(*)
18
18
  super
19
19
  @has_left_labels = true
20
+ @dot_style = 'circle'
20
21
  end
21
22
 
22
23
  private
@@ -28,7 +29,7 @@ private
28
29
 
29
30
  items_width = @graph_height / column_count
30
31
  item_width = items_width * spacing_factor / store.length
31
- padding = (items_width * (1 - spacing_factor)) / 2
32
+ padding = (items_width * (1 - spacing_factor)) / 2.0
32
33
 
33
34
  store.norm_data.each_with_index do |data_row, row_index|
34
35
  data_row.points.each_with_index do |data_point, point_index|
@@ -39,7 +40,7 @@ private
39
40
  Gruff::Renderer::Line.new(renderer, color: @marker_color).render(@graph_left, y_pos, @graph_left + @graph_width, y_pos)
40
41
  end
41
42
 
42
- Gruff::Renderer::Circle.new(renderer, color: data_row.color).render(x_pos, y_pos, x_pos + (item_width / 3.0), y_pos)
43
+ Gruff::Renderer::Dot.new(renderer, @dot_style, color: data_row.color).render(x_pos, y_pos, item_width / 3.0)
43
44
 
44
45
  draw_label(y_pos, point_index)
45
46
  end
@@ -53,9 +54,7 @@ private
53
54
  (0..marker_count).each do |index|
54
55
  marker_label = (BigDecimal(index.to_s) * BigDecimal(@increment.to_s)) + BigDecimal(minimum_value.to_s)
55
56
  x = @graph_left + ((marker_label - minimum_value) * @graph_width / @spread)
56
-
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
57
+ draw_marker_vertical_line(x, tick_mark_mode: true)
59
58
 
60
59
  unless @hide_line_numbers
61
60
  label = y_axis_label(marker_label, @increment)
@@ -70,7 +69,7 @@ private
70
69
 
71
70
  def draw_label(y_offset, index)
72
71
  draw_unique_label(index) do
73
- draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
72
+ draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], gravity: Magick::EastGravity)
74
73
  end
75
74
  end
76
75
  end
@@ -13,8 +13,6 @@
13
13
  #
14
14
  # @private
15
15
  class Gruff::BarConversion
16
- attr_writer :mode
17
-
18
16
  def initialize(top:, bottom:, minimum_value:, maximum_value:, spread:)
19
17
  @graph_top = top
20
18
  @graph_height = bottom - top
@@ -36,6 +34,7 @@ class Gruff::BarConversion
36
34
  end
37
35
 
38
36
  def get_top_bottom_scaled(data_point)
37
+ data_point = data_point.to_f
39
38
  result = []
40
39
 
41
40
  case @mode
@@ -52,9 +51,6 @@ class Gruff::BarConversion
52
51
  val = data_point - (@minimum_value / @spread)
53
52
  result[0] = @graph_top + (@graph_height * (1 - (val - @zero)))
54
53
  result[1] = @graph_top + (@graph_height * (1 - @zero))
55
- else
56
- result[0] = 0.0
57
- result[1] = 0.0
58
54
  end
59
55
 
60
56
  result
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @private
4
+ module Gruff::Base::BarMixin
5
+ def normalized_group_bars
6
+ @normalized_group_bars ||= begin
7
+ group_bars = Array.new(column_count) { [] }
8
+ store.norm_data.each_with_index do |data_row, row_index|
9
+ data_row.points.each_with_index do |data_point, point_index|
10
+ group_bars[point_index] << BarData.new(data_point, store.data[row_index].points[point_index], data_row.color)
11
+ end
12
+
13
+ # Adjust the number of each group with empty bar
14
+ (data_row.points.size..(column_count - 1)).each do |index|
15
+ group_bars[index] << BarData.new(0, nil, data_row.color)
16
+ end
17
+ end
18
+ group_bars
19
+ end
20
+ end
21
+
22
+ # @private
23
+ class BarData < Struct.new(:point, :value, :color)
24
+ end
25
+ end
@@ -49,26 +49,4 @@ module Gruff::BarValueLabel
49
49
  yield x, left_y, val, metrics.width, metrics.height
50
50
  end
51
51
  end
52
-
53
- # @private
54
- class StackedBar
55
- def initialize
56
- @bars = []
57
- end
58
-
59
- def add(bar, index)
60
- bars = @bars[index] || []
61
- bars << bar
62
- @bars[index] = bars
63
- end
64
-
65
- def prepare_rendering(format, proc_text_metrics, &block)
66
- @bars.each do |bars|
67
- value = bars.sum(&:value)
68
- bar = bars.last
69
- bar_value_label = bar.class.new(bar.coordinate, value)
70
- bar_value_label.prepare_rendering(format, proc_text_metrics, &block)
71
- end
72
- end
73
- end
74
52
  end
@@ -21,4 +21,20 @@ module Gruff::Base::StackedMixin
21
21
 
22
22
  raise "Can't handle negative values in stacked graph" if minimum_value < 0
23
23
  end
24
+
25
+ def normalized_stacked_bars
26
+ @normalized_stacked_bars ||= begin
27
+ stacked_bars = Array.new(column_count) { [] }
28
+ store.norm_data.each_with_index do |data_row, row_index|
29
+ data_row.points.each_with_index do |data_point, point_index|
30
+ stacked_bars[point_index] << BarData.new(data_point, store.data[row_index].points[point_index], data_row.color)
31
+ end
32
+ end
33
+ stacked_bars
34
+ end
35
+ end
36
+
37
+ # @private
38
+ class BarData < Struct.new(:point, :value, :color)
39
+ end
24
40
  end
@@ -40,15 +40,18 @@ private
40
40
  @minimum_bin = nil
41
41
  @maximum_bin = nil
42
42
  end
43
- private :initialize_attributes
44
43
 
45
44
  def setup_data
46
45
  @data.each do |(name, data_points, color)|
47
- bins, freqs = HistogramArray.new(data_points).histogram(bin_width: @bin_width, min: @minimum_bin, max: @maximum_bin)
48
- bins.each_with_index do |bin, index|
49
- @labels[index] = bin
46
+ if data_points.empty?
47
+ store.add(name, [], color)
48
+ else
49
+ bins, freqs = HistogramArray.new(data_points).histogram(bin_width: @bin_width, min: @minimum_bin, max: @maximum_bin)
50
+ bins.each_with_index do |bin, index|
51
+ @labels[index] = bin
52
+ end
53
+ store.add(name, freqs, color)
50
54
  end
51
- store.add(name, freqs, color)
52
55
  end
53
56
 
54
57
  super
data/lib/gruff/line.rb CHANGED
@@ -25,7 +25,7 @@ class Gruff::Line < Gruff::Base
25
25
  attr_writer :line_width
26
26
  attr_writer :dot_radius
27
27
 
28
- # default is +'circle'+, other options include square.
28
+ # default is +'circle'+, other options include +square+ and +diamond+.
29
29
  attr_writer :dot_style
30
30
 
31
31
  # Hide parts of the graph to fit more data points, or for a different appearance.
@@ -81,6 +81,30 @@ class Gruff::Line < Gruff::Base
81
81
  @reference_lines[:baseline][:color] = new_value
82
82
  end
83
83
 
84
+ # Input the data in the graph.
85
+ #
86
+ # Parameters are an array where the first element is the name of the dataset
87
+ # and the value is an array of values to plot.
88
+ #
89
+ # Can be called multiple times with different datasets for a multi-valued
90
+ # graph.
91
+ #
92
+ # If the color argument is nil, the next color from the default theme will
93
+ # be used.
94
+ #
95
+ # @param name [String, Symbol] The name of the dataset.
96
+ # @param data_points [Array] The array of dataset.
97
+ # @param color [String] The color for drawing graph of dataset.
98
+ #
99
+ # @note
100
+ # If you want to use a preset theme, you must set it before calling {#data}.
101
+ #
102
+ # @example
103
+ # data("Bart S.", [95, 45, 78, 89, 88, 76], '#ffcc00')
104
+ def data(name, data_points = [], color = nil)
105
+ store.add(name, nil, data_points, color)
106
+ end
107
+
84
108
  # This method allows one to plot a dataset with both X and Y data.
85
109
  #
86
110
  # @overload dataxy(name, x_data_points = [], y_data_points = [], color = nil)
@@ -131,7 +155,7 @@ class Gruff::Line < Gruff::Base
131
155
  raise ArgumentError, 'x_data_points.length != y_data_points.length!' if x_data_points.length != y_data_points.length
132
156
 
133
157
  # call the existing data routine for the x/y data.
134
- store.add(name, y_data_points, color, x_data_points)
158
+ store.add(name, x_data_points, y_data_points, color)
135
159
  end
136
160
 
137
161
  private
@@ -177,50 +201,53 @@ private
177
201
  def draw_graph
178
202
  # Check to see if more than one datapoint was given. NaN can result otherwise.
179
203
  @x_increment = column_count > 1 ? @graph_width / (column_count - 1) : @graph_width
204
+ @x_increment = @x_increment.to_f
180
205
 
181
206
  @reference_lines.each_value do |curr_reference_line|
182
207
  draw_horizontal_reference_line(curr_reference_line) if curr_reference_line.key?(:norm_value)
183
208
  draw_vertical_reference_line(curr_reference_line) if curr_reference_line.key?(:index)
184
209
  end
185
210
 
186
- store.norm_data.each do |data_row|
187
- prev_x = prev_y = nil
211
+ stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 4.0), 5.0)
212
+ circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 2.5), 5.0)
188
213
 
189
- one_point = contains_one_point_only?(data_row)
214
+ store.norm_data.each do |data_row|
215
+ poly_points_group = [[]]
190
216
 
191
217
  data_row.coordinates.each_with_index do |(x_data, y_data), index|
218
+ poly_points = poly_points_group.last
219
+
192
220
  new_x = begin
193
221
  if x_data.nil?
194
222
  # use the old method: equally spaced points along the x-axis
195
223
  @graph_left + (@x_increment * index)
196
224
  else
197
- get_x_coord(x_data, @graph_width, @graph_left)
225
+ @graph_left + (x_data * @graph_width)
198
226
  end
199
227
  end
200
228
  draw_label_for_x_data(x_data, new_x, index)
201
229
 
202
- unless y_data # we can't draw a line for a null data point, we can still label the axis though
203
- prev_x = prev_y = nil
230
+ unless y_data
231
+ # we can't draw a line for a null data point, we can still label the axis though.
232
+ # Split the polygonal line into separate groups of points for polyline.
233
+ poly_points_group << []
204
234
  next
205
235
  end
206
236
 
207
237
  new_y = @graph_top + (@graph_height - (y_data * @graph_height))
208
238
 
209
- # Reset each time to avoid thin-line errors
210
- stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 4), 5.0)
211
- circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 2.5), 5.0)
212
-
213
- if !@hide_lines && prev_x && prev_y
214
- Gruff::Renderer::Line.new(renderer, color: data_row.color, width: stroke_width)
215
- .render(prev_x, prev_y, new_x, new_y)
216
- end
239
+ poly_points << new_x
240
+ poly_points << new_y
217
241
 
218
- if one_point || !@hide_dots
242
+ if contains_one_point_only?(data_row) || !@hide_dots
219
243
  Gruff::Renderer::Dot.new(renderer, @dot_style, color: data_row.color, width: stroke_width).render(new_x, new_y, circle_radius)
220
244
  end
245
+ end
221
246
 
222
- prev_x = new_x
223
- prev_y = new_y
247
+ unless @hide_lines
248
+ poly_points_group.each do |poly_points|
249
+ Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: stroke_width).render(poly_points) unless poly_points.empty?
250
+ end
224
251
  end
225
252
  end
226
253
  end
@@ -273,10 +300,7 @@ private
273
300
  return unless @show_vertical_markers
274
301
 
275
302
  (0..@marker_x_count).each do |index|
276
- x = @graph_left + @graph_width - (index * @graph_width / @marker_x_count)
277
-
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
303
+ draw_marker_vertical_line(@graph_left + @graph_width - (index * @graph_width / @marker_x_count))
280
304
  end
281
305
  end
282
306
 
@@ -290,10 +314,6 @@ private
290
314
  end
291
315
  end
292
316
 
293
- def get_x_coord(x_data_point, width, offset)
294
- (x_data_point * width) + offset
295
- end
296
-
297
317
  def contains_one_point_only?(data_row)
298
318
  data_row.y_points.compact.count == 1
299
319
  end
@@ -28,7 +28,7 @@ module Gruff
28
28
  @hide_line_numbers = true
29
29
 
30
30
  @marker_font.size = 50.0
31
- @legend_font.size = 60.0
31
+ @legend_font.size = 50.0
32
32
 
33
33
  @minimum_value = 0.0
34
34
  end
@@ -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((store.length * calculate_line_height) + @top_margin + @bottom_margin)
25
25
 
26
26
  @original_rows = @raw_rows
27
27
  @original_columns = @raw_columns
@@ -32,7 +32,7 @@ module Gruff
32
32
  @columns += calculate_legend_width + @left_margin
33
33
  else
34
34
  font = @legend_font.dup
35
- font.size = scale_fontsize(font.size)
35
+ font.size = scale(font.size)
36
36
  @rows += store.length * calculate_caps_height(font) * 1.7
37
37
  end
38
38
 
@@ -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(width + (40 * 1.7))
49
49
  end
50
50
 
51
51
  ##
@@ -69,9 +69,9 @@ module Gruff
69
69
 
70
70
  @legend_labels.each_with_index do |legend_label, index|
71
71
  # Draw label
72
- label = truncate_legend_label(legend_label)
73
- text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
74
72
  x_offset = current_x_offset + (legend_square_width * 1.7)
73
+ label = truncate_legend_label(legend_label, x_offset)
74
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
75
75
  text_renderer.add_to_render_queue(@raw_columns, 1.0, x_offset, current_y_offset, Magick::WestGravity)
76
76
 
77
77
  # Now draw box with color of this dataset
@@ -90,17 +90,21 @@ module Gruff
90
90
  #
91
91
  # Department of Hu...
92
92
 
93
- def truncate_legend_label(label)
93
+ def truncate_legend_label(label, x_offset)
94
94
  truncated_label = label.to_s
95
95
 
96
96
  font = @legend_font.dup
97
- font.size = scale_fontsize(font.size)
98
- max_width = @columns - @legend_left_margin - @right_margin
99
- while calculate_width(font, truncated_label) > max_width && truncated_label.length > 1
97
+ font.size = scale(font.size)
98
+ max_width = @columns - scale(x_offset) - @right_margin
99
+ while calculate_width(font, "#{truncated_label}...") > max_width && truncated_label.length > 1
100
100
  truncated_label = truncated_label[0..truncated_label.length - 2]
101
101
  end
102
102
  truncated_label + (truncated_label.length < label.to_s.length ? '...' : '')
103
103
  end
104
+
105
+ def scale(value)
106
+ value * @scale
107
+ end
104
108
  end
105
109
  end
106
110
  end
@@ -26,8 +26,8 @@ module Gruff
26
26
  @hide_title = true
27
27
  @hide_line_numbers = true
28
28
 
29
- @marker_font.size = 60.0
30
- @legend_font.size = 60.0
29
+ @marker_font.size = 50.0
30
+ @legend_font.size = 50.0
31
31
  end
32
32
 
33
33
  def setup_data
data/lib/gruff/net.rb CHANGED
@@ -43,8 +43,25 @@ private
43
43
  @marker_font.bold = true
44
44
  end
45
45
 
46
+ def setup_drawing
47
+ @center_labels_over_point = false
48
+ super
49
+ end
50
+
51
+ def setup_graph_measurements
52
+ super
53
+
54
+ @radius = @graph_height / 2.0
55
+ @circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 2.5), 5.0)
56
+ @stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 4.0), 5.0)
57
+ @center_x = @graph_left + (@graph_width / 2.0)
58
+ @center_y = @graph_top + (@graph_height / 2.0) + 10
59
+ end
60
+
46
61
  def draw_graph
47
62
  store.norm_data.each do |data_row|
63
+ poly_points = []
64
+
48
65
  data_row.points.each_with_index do |data_point, index|
49
66
  next if data_point.nil?
50
67
 
@@ -52,6 +69,10 @@ private
52
69
  point_distance = data_point * @radius
53
70
  start_x = @center_x + (Math.sin(rad_pos) * point_distance)
54
71
  start_y = @center_y - (Math.cos(rad_pos) * point_distance)
72
+ if poly_points.empty?
73
+ poly_points << start_x
74
+ poly_points << start_y
75
+ end
55
76
 
56
77
  next_index = index + 1 < data_row.points.length ? index + 1 : 0
57
78
 
@@ -59,25 +80,17 @@ private
59
80
  next_point_distance = data_row.points[next_index] * @radius
60
81
  end_x = @center_x + (Math.sin(next_rad_pos) * next_point_distance)
61
82
  end_y = @center_y - (Math.cos(next_rad_pos) * next_point_distance)
62
-
63
- Gruff::Renderer::Line.new(renderer, color: data_row.color, width: @stroke_width).render(start_x, start_y, end_x, end_y)
83
+ poly_points << end_x
84
+ poly_points << end_y
64
85
 
65
86
  unless @hide_dots
66
87
  circle_renderer = Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: @stroke_width)
67
88
  circle_renderer.render(start_x, start_y, start_x - @circle_radius, start_y)
68
89
  end
69
90
  end
70
- end
71
- end
72
-
73
- def setup_drawing
74
- super
75
91
 
76
- @radius = @graph_height / 2.0
77
- @circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 2.5), 5.0)
78
- @stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 4), 5.0)
79
- @center_x = @graph_left + (@graph_width / 2.0)
80
- @center_y = @graph_top + (@graph_height / 2.0) + 10
92
+ Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: @stroke_width).render(poly_points) unless poly_points.empty?
93
+ end
81
94
  end
82
95
 
83
96
  # the lines connecting in the center, with the first line vertical
@@ -102,6 +115,6 @@ private
102
115
  x = x_offset + ((radius + LABEL_MARGIN) * Math.sin(deg2rad(angle)))
103
116
  y = y_offset - ((radius + LABEL_MARGIN) * Math.cos(deg2rad(angle)))
104
117
 
105
- draw_label_at(1.0, 1.0, x, y, amount, Magick::CenterGravity)
118
+ draw_label_at(1.0, 1.0, x, y, amount, gravity: Magick::CenterGravity)
106
119
  end
107
120
  end
data/lib/gruff/pie.rb CHANGED
@@ -38,7 +38,7 @@ class Gruff::Pie < Gruff::Base
38
38
 
39
39
  # Can be used to make the pie start cutting slices at the top (-90.0)
40
40
  # or at another angle. Default is +-90.0+, which starts at 3 o'clock.
41
- # @deprecated Please use +start_degree+ attribute instead.
41
+ # @deprecated Please use {#start_degree=} instead.
42
42
  def zero_degree=(value)
43
43
  warn '#zero_degree= is deprecated. Please use `start_degree` attribute instead'
44
44
  @start_degree = value
@@ -61,6 +61,11 @@ private
61
61
  @label_formatting = ->(value, percentage) { @show_values_as_labels ? value.to_s : "#{percentage}%" }
62
62
  end
63
63
 
64
+ def setup_drawing
65
+ @center_labels_over_point = false
66
+ super
67
+ end
68
+
64
69
  def draw_graph
65
70
  slices.each do |slice|
66
71
  if slice.value > 0
@@ -136,7 +141,7 @@ private
136
141
  if slice.percentage >= @hide_labels_less_than
137
142
  x, y = label_coordinates_for slice
138
143
  label = @label_formatting.call(slice.value, slice.percentage)
139
- draw_label_at(1.0, 1.0, x, y, label, Magick::CenterGravity)
144
+ draw_label_at(1.0, 1.0, x, y, label, gravity: Magick::CenterGravity)
140
145
  end
141
146
  end
142
147