gruff 0.15.0-java → 0.18.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +21 -5
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +0 -12
  5. data/CHANGELOG.md +52 -0
  6. data/README.md +14 -3
  7. data/gruff.gemspec +3 -4
  8. data/lib/gruff/accumulator_bar.rb +1 -1
  9. data/lib/gruff/area.rb +6 -4
  10. data/lib/gruff/bar.rb +53 -32
  11. data/lib/gruff/base.rb +297 -186
  12. data/lib/gruff/bezier.rb +4 -2
  13. data/lib/gruff/box.rb +180 -0
  14. data/lib/gruff/bubble.rb +99 -0
  15. data/lib/gruff/bullet.rb +5 -5
  16. data/lib/gruff/candlestick.rb +120 -0
  17. data/lib/gruff/dot.rb +11 -12
  18. data/lib/gruff/font.rb +3 -0
  19. data/lib/gruff/helper/bar_conversion.rb +6 -10
  20. data/lib/gruff/helper/bar_mixin.rb +25 -0
  21. data/lib/gruff/helper/bar_value_label.rb +24 -43
  22. data/lib/gruff/helper/stacked_mixin.rb +19 -1
  23. data/lib/gruff/histogram.rb +9 -6
  24. data/lib/gruff/line.rb +67 -43
  25. data/lib/gruff/mini/legend.rb +15 -11
  26. data/lib/gruff/net.rb +23 -18
  27. data/lib/gruff/patch/string.rb +1 -0
  28. data/lib/gruff/pie.rb +26 -12
  29. data/lib/gruff/renderer/circle.rb +3 -1
  30. data/lib/gruff/renderer/dash_line.rb +3 -2
  31. data/lib/gruff/renderer/dot.rb +28 -15
  32. data/lib/gruff/renderer/line.rb +1 -3
  33. data/lib/gruff/renderer/rectangle.rb +6 -2
  34. data/lib/gruff/renderer/renderer.rb +0 -4
  35. data/lib/gruff/renderer/text.rb +7 -1
  36. data/lib/gruff/scatter.rb +84 -81
  37. data/lib/gruff/side_bar.rb +64 -31
  38. data/lib/gruff/side_stacked_bar.rb +43 -55
  39. data/lib/gruff/spider.rb +52 -14
  40. data/lib/gruff/stacked_area.rb +18 -8
  41. data/lib/gruff/stacked_bar.rb +59 -29
  42. data/lib/gruff/store/xy_data.rb +8 -9
  43. data/lib/gruff/store/xy_pointsizes_data.rb +60 -0
  44. data/lib/gruff/version.rb +1 -1
  45. data/lib/gruff.rb +11 -12
  46. metadata +9 -6
  47. data/lib/gruff/scene.rb +0 -208
  48. data/lib/gruff/store/custom_data.rb +0 -36
@@ -23,10 +23,6 @@ module Gruff
23
23
  end
24
24
  end
25
25
 
26
- def background_image=(image)
27
- @image = image
28
- end
29
-
30
26
  def background(columns, rows, scale, theme_options)
31
27
  case theme_options[:background_colors]
32
28
  when Array
@@ -25,6 +25,7 @@ module Gruff
25
25
  end
26
26
 
27
27
  def render(width, height, x, y, gravity = Magick::NorthGravity)
28
+ @renderer.draw.push
28
29
  @renderer.draw.rotation = @rotation if @rotation
29
30
  @renderer.draw.fill = @font.color
30
31
  @renderer.draw.stroke = 'transparent'
@@ -37,9 +38,11 @@ module Gruff
37
38
  x, y,
38
39
  @text, @renderer.scale)
39
40
  @renderer.draw.rotation = -@rotation if @rotation
41
+ @renderer.draw.pop
40
42
  end
41
43
 
42
44
  def metrics
45
+ @renderer.draw.push
43
46
  @renderer.draw.font = @font.file_path
44
47
  @renderer.draw.font_weight = @font.weight
45
48
  @renderer.draw.pointsize = @font.size
@@ -50,7 +53,10 @@ module Gruff
50
53
  # So, in here, it just escape % in order to avoid SEGV.
51
54
  text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
52
55
 
53
- @renderer.draw.get_type_metrics(@renderer.image, text)
56
+ metrics = @renderer.draw.get_type_metrics(@renderer.image, text)
57
+ @renderer.draw.pop
58
+
59
+ metrics
54
60
  end
55
61
  end
56
62
  end
data/lib/gruff/scatter.rb CHANGED
@@ -24,24 +24,35 @@ class Gruff::Scatter < Gruff::Base
24
24
  attr_writer :circle_radius
25
25
  attr_writer :stroke_width
26
26
 
27
- # Allow disabling the significant rounding when labeling the X axis.
28
- # This is useful when working with a small range of high values (for example, a date range of months, while seconds as units).
29
- attr_writer :disable_significant_rounding_x_axis
30
-
31
27
  # Allow for vertical marker lines.
32
28
  attr_writer :show_vertical_markers
33
29
 
34
- # Allow using vertical labels in the X axis (and setting the label margin).
35
- attr_writer :x_label_margin
36
- attr_writer :use_vertical_x_labels
37
-
38
30
  # Allow enabling vertical lines. When you have a lot of data, they can work great.
39
- # @deprecated Please use +show_vertical_markers+ attribute instead.
31
+ # @deprecated Please use {#show_vertical_markers=} instead.
40
32
  def enable_vertical_line_markers=(value)
41
33
  warn '#enable_vertical_line_markers= is deprecated. Please use `show_vertical_markers` attribute instead'
42
34
  @show_vertical_markers = value
43
35
  end
44
36
 
37
+ # Allow using vertical labels in the X axis.
38
+ # @deprecated Please use {Gruff::Base#label_rotation=} instead.
39
+ def use_vertical_x_labels=(_value)
40
+ warn '#use_vertical_x_labels= is deprecated. It is no longer effective. Please use `#label_rotation=` instead'
41
+ end
42
+
43
+ # Allow using vertical labels in the X axis (and setting the label margin).
44
+ # @deprecated
45
+ def x_label_margin=(_value)
46
+ warn '#x_label_margin= is deprecated. It is no longer effective.'
47
+ end
48
+
49
+ # Allow disabling the significant rounding when labeling the X axis.
50
+ # This is useful when working with a small range of high values (for example, a date range of months, while seconds as units).
51
+ # @deprecated
52
+ def disable_significant_rounding_x_axis=(_value)
53
+ warn '#disable_significant_rounding_x_axis= is deprecated. It is no longer effective.'
54
+ end
55
+
45
56
  # The first parameter is the name of the dataset. The next two are the
46
57
  # x and y axis data points contain in their own array in that respective
47
58
  # order. The final parameter is the color.
@@ -55,11 +66,10 @@ class Gruff::Scatter < Gruff::Base
55
66
  # @note If you want to use a preset theme, you must set it before calling {#data}.
56
67
  #
57
68
  # @param name [String, Symbol] containing the name of the dataset.
58
- # @param x_data_points [Array] An Array of of x-axis data points.
59
- # @param y_data_points [Array] An Array of of y-axis data points.
69
+ # @param x_data_points [Array] An Array of x-axis data points.
70
+ # @param y_data_points [Array] An Array of y-axis data points.
60
71
  # @param color [String] The hex string for the color of the dataset. Defaults to nil.
61
72
  #
62
- #
63
73
  # @raise [ArgumentError] Data points contain nil values.
64
74
  # This error will get raised if either the x or y axis data points array
65
75
  # contains a +nil+ value. The graph will not make an assumption
@@ -88,7 +98,7 @@ class Gruff::Scatter < Gruff::Base
88
98
  raise ArgumentError, 'x_data_points.length != y_data_points.length!' if x_data_points.length != y_data_points.length
89
99
 
90
100
  # Call the existing data routine for the x/y axis data
91
- store.add(name, y_data_points, color, x_data_points)
101
+ store.add(name, x_data_points, y_data_points, color)
92
102
  end
93
103
 
94
104
  alias dataxy data
@@ -102,56 +112,55 @@ private
102
112
  def initialize_attributes
103
113
  super
104
114
 
105
- @baseline_x_color = @baseline_y_color = 'red'
106
- @baseline_x_value = @baseline_y_value = nil
107
115
  @circle_radius = nil
108
- @disable_significant_rounding_x_axis = false
109
116
  @show_vertical_markers = false
110
117
  @marker_x_count = nil
111
118
  @maximum_x_value = @minimum_x_value = nil
112
119
  @stroke_width = nil
113
- @use_vertical_x_labels = false
114
- @x_label_margin = nil
115
120
  end
116
121
 
117
- def draw_graph
118
- # Check to see if more than one datapoint was given. NaN can result otherwise.
119
- @x_increment = @x_spread > 1 ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
122
+ def setup_drawing
123
+ @center_labels_over_point = false
124
+ super
125
+ end
120
126
 
127
+ def setup_data
128
+ # TODO: Need to get x-axis labels working. Current behavior will be to not allow.
129
+ @labels = {}
130
+
131
+ # Update the global min/max values for the x data
132
+ @maximum_x_value = (@maximum_x_value || store.max_x).to_f
133
+ @minimum_x_value = (@minimum_x_value || store.min_x).to_f
134
+
135
+ if @x_axis_increment
136
+ # TODO: Make this work for negative values
137
+ @maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment.to_f].max
138
+ @minimum_x_value = @minimum_x_value.floor
139
+ end
140
+
141
+ super
142
+ end
143
+
144
+ def draw_graph
121
145
  store.norm_data.each do |data_row|
122
146
  data_row.coordinates.each do |x_value, y_value|
123
147
  next if y_value.nil? || x_value.nil?
124
148
 
125
- new_x = get_x_coord(x_value, @graph_width, @graph_left)
126
- new_y = @graph_top + (@graph_height - y_value * @graph_height)
149
+ new_x = @graph_left + (x_value * @graph_width)
150
+ new_y = @graph_bottom - (y_value * @graph_height)
127
151
 
128
152
  # Reset each time to avoid thin-line errors
129
- stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
153
+ stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4.0), 5.0)
130
154
  circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
131
155
  Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
132
156
  end
133
157
  end
134
158
  end
135
159
 
136
- def setup_data
137
- # Update the global min/max values for the x data
138
- @maximum_x_value ||= store.max_x
139
- @minimum_x_value ||= store.min_x
140
-
141
- super
142
- end
143
-
144
- def setup_drawing
145
- # TODO: Need to get x-axis labels working. Current behavior will be to not allow.
146
- @labels = {}
147
-
148
- super
149
- end
150
-
151
160
  def calculate_spread
152
161
  super
153
162
  @x_spread = @maximum_x_value.to_f - @minimum_x_value.to_f
154
- @x_spread = @x_spread > 0 ? @x_spread : 1
163
+ @x_spread = @x_spread > 0 ? @x_spread : 1.0
155
164
  end
156
165
 
157
166
  def normalize
@@ -165,57 +174,51 @@ private
165
174
  super
166
175
  return if @hide_line_markers
167
176
 
168
- if @x_axis_increment.nil?
169
- # TODO: Do the same for larger numbers...100, 75, 50, 25
170
- if @marker_x_count.nil?
171
- (3..7).each do |lines|
172
- if @x_spread % lines == 0.0
173
- @marker_x_count = lines
174
- break
175
- end
176
- end
177
- @marker_x_count ||= 4
178
- end
179
- @x_increment = @x_spread > 0 ? (@x_spread / @marker_x_count) : 1
180
- unless @disable_significant_rounding_x_axis
181
- @x_increment = significant(@x_increment)
182
- end
183
- else
184
- # TODO: Make this work for negative values
185
- @maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment].max
186
- @minimum_x_value = @minimum_x_value.floor
187
- calculate_spread
188
- normalize
189
-
190
- @marker_x_count = (@x_spread / @x_axis_increment).to_i
191
- @x_increment = @x_axis_increment
192
- end
193
- increment_x_scaled = @graph_width.to_f / (@x_spread / @x_increment)
177
+ increment_x_scaled = (@graph_width / (@x_spread / x_increment)).to_f
194
178
 
195
179
  # Draw vertical line markers and annotate with numbers
196
- (0..@marker_x_count).each do |index|
180
+ (0..marker_x_count).each do |index|
197
181
  # TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
198
182
  if @show_vertical_markers
199
- x = @graph_left + @graph_width - index.to_f * increment_x_scaled
200
-
201
- line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
202
- line_renderer.render(x, @graph_top, x, @graph_bottom)
183
+ draw_marker_vertical_line(@graph_left + (index * increment_x_scaled))
203
184
  end
204
185
 
205
186
  unless @hide_line_numbers
206
- marker_label = BigDecimal(index.to_s) * BigDecimal(@x_increment.to_s) + BigDecimal(@minimum_x_value.to_s)
207
- y_offset = @graph_bottom + (@x_label_margin || LABEL_MARGIN)
208
- x_offset = get_x_coord(index.to_f, increment_x_scaled, @graph_left)
209
-
210
- label = x_axis_label(marker_label, @x_increment)
211
- rotation = -90.0 if @use_vertical_x_labels
212
- text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font, rotation: rotation)
213
- text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
187
+ marker_label = (BigDecimal(index.to_s) * BigDecimal(x_increment.to_s)) + BigDecimal(@minimum_x_value.to_s)
188
+ label = x_axis_label(marker_label, x_increment)
189
+ x = @graph_left + (increment_x_scaled * index)
190
+ y = @graph_bottom
191
+ x_offset, y_offset = calculate_label_offset(@marker_font, label, LABEL_MARGIN, @label_rotation)
192
+
193
+ draw_label_at(1.0, 1.0, x + x_offset, y + y_offset, label, rotation: @label_rotation)
214
194
  end
215
195
  end
216
196
  end
217
197
 
218
- def get_x_coord(x_data_point, width, offset)
219
- x_data_point * width + offset
198
+ def marker_x_count
199
+ # TODO: Do the same for larger numbers...100, 75, 50, 25
200
+ @marker_x_count ||= begin
201
+ if @x_axis_increment.nil?
202
+ count = nil
203
+ (3..7).each do |lines|
204
+ if @x_spread % lines == 0.0
205
+ count = lines and break
206
+ end
207
+ end
208
+ count || 4
209
+ else
210
+ (@x_spread / @x_axis_increment).to_i
211
+ end
212
+ end
213
+ end
214
+
215
+ def x_increment
216
+ @x_increment ||= begin
217
+ if @x_axis_increment.nil?
218
+ @x_spread > 0 ? significant(@x_spread / marker_x_count) : 1.0
219
+ else
220
+ @x_axis_increment.to_f
221
+ end
222
+ end
220
223
  end
221
224
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'helper/bar_mixin'
4
+
3
5
  # Graph with individual horizontal bars instead of vertical bars.
4
6
  #
5
7
  # Here's how to set up a Gruff::SideBar.
@@ -19,6 +21,8 @@
19
21
  # g.write('sidebar.png')
20
22
  #
21
23
  class Gruff::SideBar < Gruff::Base
24
+ include BarMixin
25
+
22
26
  # Spacing factor applied between bars.
23
27
  attr_writer :bar_spacing
24
28
 
@@ -36,6 +40,15 @@ class Gruff::SideBar < Gruff::Base
36
40
  # Prevent drawing of column labels left of a side bar graph. Default is +false+.
37
41
  attr_writer :hide_labels
38
42
 
43
+ # Value to avoid completely overwriting the coordinate axis
44
+ AXIS_MARGIN = 0.5
45
+ private_constant :AXIS_MARGIN
46
+
47
+ def initialize(*)
48
+ super
49
+ @has_left_labels = true
50
+ end
51
+
39
52
  # With Side Bars use the data label for the marker value to the left of the bar.
40
53
  # @deprecated
41
54
  def use_data_label=(_value)
@@ -51,7 +64,6 @@ private
51
64
  @label_formatting = nil
52
65
  @show_labels_for_bar_values = false
53
66
  @hide_labels = false
54
- @has_left_labels = true
55
67
  end
56
68
 
57
69
  def hide_labels?
@@ -59,20 +71,37 @@ private
59
71
  end
60
72
 
61
73
  def hide_left_label_area?
62
- hide_labels?
74
+ hide_labels? && @y_axis_label.nil?
63
75
  end
64
76
 
65
77
  def hide_bottom_label_area?
66
- @hide_line_markers
78
+ @hide_line_markers && @x_axis_label.nil? && @legend_at_bottom == false
67
79
  end
68
80
 
69
- # Value to avoid completely overwriting the coordinate axis
70
- AXIS_MARGIN = 0.5
81
+ def setup_graph_measurements
82
+ super
83
+ return if @hide_line_markers
84
+
85
+ if @show_labels_for_bar_values
86
+ if maximum_value >= 0
87
+ _, metrics = Gruff::BarValueLabel.metrics(maximum_value, @label_formatting, proc_text_metrics)
88
+ @graph_right -= metrics.width
89
+ end
90
+
91
+ if minimum_value < 0
92
+ _, metrics = Gruff::BarValueLabel.metrics(minimum_value, @label_formatting, proc_text_metrics)
93
+ width = metrics.width + LABEL_MARGIN
94
+ @graph_left += width - @graph_left if width > @graph_left
95
+ end
96
+
97
+ @graph_width = @graph_right - @graph_left
98
+ end
99
+ end
71
100
 
72
101
  def draw_graph
73
102
  # Setup spacing.
74
103
  #
75
- bars_width = (@graph_height - calculate_spacing) / column_count.to_f
104
+ bars_width = (@graph_height - calculate_spacing) / column_count
76
105
  bar_width = bars_width / store.length
77
106
  padding = (bar_width * (1 - @bar_spacing)) / 2
78
107
 
@@ -82,30 +111,32 @@ private
82
111
  minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
83
112
  )
84
113
 
85
- store.norm_data.each_with_index do |data_row, row_index|
86
- data_row.points.each_with_index do |data_point, point_index|
87
- group_spacing = @group_spacing * @scale * point_index
88
-
89
- left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
90
- right_y = left_y + bar_width * @bar_spacing
114
+ group_left_y = @graph_top
91
115
 
92
- left_x, right_x = conversion.get_top_bottom_scaled(data_point).sort
116
+ normalized_group_bars.each_with_index do |group_bars, group_index|
117
+ right_y = 0
118
+ group_bars.each_with_index do |bar, index|
119
+ left_y = group_left_y + (bar_width * index) + padding
120
+ right_y = left_y + (bar_width * @bar_spacing)
93
121
 
94
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
95
- rect_renderer.render(left_x + AXIS_MARGIN, left_y, right_x + AXIS_MARGIN, right_y)
96
-
97
- # Calculate center based on bar_width and current row
98
- label_center = left_y + bars_width / 2
122
+ bottom_x, top_x = conversion.get_top_bottom_scaled(bar.point).sort
123
+ if bar.point != 0
124
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
125
+ rect_renderer.render(bottom_x + AXIS_MARGIN, left_y, top_x, right_y)
126
+ end
99
127
 
100
- # Subtract half a bar width to center left if requested
101
- draw_label(label_center, point_index)
102
- if @show_labels_for_bar_values
103
- bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
104
- bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
105
- draw_value_label(x, y, text)
128
+ if @show_labels_for_bar_values && bar.value
129
+ bar_value_label = Gruff::BarValueLabel::SideBar.new([bottom_x, left_y, top_x, right_y], bar.value)
130
+ bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
131
+ draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
106
132
  end
107
133
  end
108
134
  end
135
+
136
+ label_center = group_left_y + (bars_width / 2.0)
137
+ draw_label(label_center, group_index)
138
+
139
+ group_left_y = right_y + padding + @group_spacing
109
140
  end
110
141
  end
111
142
 
@@ -118,17 +149,15 @@ private
118
149
  number_of_lines = 1 if number_of_lines == 0
119
150
 
120
151
  # TODO: Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
121
- increment = significant(@spread.to_f / number_of_lines)
152
+ increment = significant(@spread / number_of_lines)
122
153
  (0..number_of_lines).each do |index|
123
154
  line_diff = (@graph_right - @graph_left) / number_of_lines
124
155
  x = @graph_right - (line_diff * index) - 1
125
-
126
- line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
127
- line_renderer.render(x, @graph_bottom, x, @graph_top)
156
+ draw_marker_vertical_line(x)
128
157
 
129
158
  unless @hide_line_numbers
130
159
  diff = index - number_of_lines
131
- marker_label = BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s) + BigDecimal(minimum_value.to_s)
160
+ marker_label = (BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s)) + BigDecimal(minimum_value.to_s)
132
161
  label = x_axis_label(marker_label, @increment)
133
162
  text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
134
163
  text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + LABEL_MARGIN, Magick::CenterGravity)
@@ -141,11 +170,15 @@ private
141
170
 
142
171
  def draw_label(y_offset, index)
143
172
  draw_unique_label(index) do
144
- draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
173
+ draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], gravity: Magick::EastGravity)
145
174
  end
146
175
  end
147
176
 
148
177
  def calculate_spacing
149
- @scale * @group_spacing * (column_count - 1)
178
+ @group_spacing * (column_count - 1)
179
+ end
180
+
181
+ def proc_text_metrics
182
+ ->(text) { text_metrics(@marker_font, text) }
150
183
  end
151
184
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'helper/stacked_mixin'
4
+
3
5
  #
4
6
  # New gruff graph type added to enable sideways stacking bar charts
5
7
  # (basically looks like a x/y flip of a standard stacking bar chart)
@@ -39,6 +41,11 @@ class Gruff::SideStackedBar < Gruff::SideBar
39
41
  # Prevent drawing of column labels left of a side stacked bar graph. Default is +false+.
40
42
  attr_writer :hide_labels
41
43
 
44
+ def initialize(*)
45
+ super
46
+ @has_left_labels = true
47
+ end
48
+
42
49
  private
43
50
 
44
51
  def initialize_attributes
@@ -48,7 +55,7 @@ private
48
55
  @label_formatting = nil
49
56
  @show_labels_for_bar_values = false
50
57
  @hide_labels = false
51
- @has_left_labels = true
58
+ @minimum_value = 0.0
52
59
  end
53
60
 
54
61
  def setup_data
@@ -56,67 +63,48 @@ private
56
63
  super
57
64
  end
58
65
 
59
- def hide_labels?
60
- @hide_labels
61
- end
62
-
63
- def hide_left_label_area?
64
- hide_labels?
65
- end
66
-
67
- def hide_bottom_label_area?
68
- @hide_line_markers
69
- end
70
-
71
66
  def draw_graph
72
67
  # Setup spacing.
73
68
  #
74
69
  # Columns sit stacked.
75
- bar_width = @graph_height / column_count.to_f
76
- height = Array.new(column_count, 0)
77
- length = Array.new(column_count, @graph_left)
70
+ bar_width = @graph_height / column_count
78
71
  padding = (bar_width * (1 - @bar_spacing)) / 2
79
- stack_bar_value_label = Gruff::BarValueLabel::StackedBar.new
80
-
81
- store.norm_data.each_with_index do |data_row, row_index|
82
- data_row.points.each_with_index do |data_point, point_index|
83
- ## using the original calculations from the stacked bar chart to get the difference between
84
- ## part of the bart chart we wish to stack.
85
- temp1 = @graph_left + (@graph_width -
86
- data_point * @graph_width -
87
- height[point_index]) + 1
88
- temp2 = @graph_left + @graph_width - height[point_index] - 1
89
- difference = temp2 - temp1
90
- difference = 0 if row_index == 0 && difference < 0
91
-
92
- left_x = length[point_index]
93
- left_y = @graph_top + (bar_width * point_index) + padding
94
- right_x = left_x + difference - @segment_spacing
95
- right_y = left_y + bar_width * @bar_spacing
96
- length[point_index] += difference
97
- height[point_index] += (data_point * @graph_width - 2)
98
-
99
- bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
100
- stack_bar_value_label.add(bar_value_label, point_index)
101
-
102
- # if a data point is 0 it can result in weird really thing lines
103
- # that shouldn't even be there being drawn on top of the existing
104
- # bar - this is bad
105
- if data_point != 0
106
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
107
- rect_renderer.render(left_x, left_y, right_x, right_y)
108
- # Calculate center based on bar_width and current row
109
- end
110
- # we still need to draw the labels
111
- # Calculate center based on bar_width and current row
112
- label_center = left_y + bar_width / 2
113
- draw_label(label_center, point_index)
72
+
73
+ # Setup the BarConversion Object
74
+ conversion = Gruff::BarConversion.new(
75
+ top: @graph_right, bottom: @graph_left,
76
+ minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
77
+ )
78
+
79
+ proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
80
+
81
+ normalized_stacked_bars.each_with_index do |stacked_bars, stacked_index|
82
+ total = 0
83
+ left_y = @graph_top + (bar_width * stacked_index) + padding
84
+ right_y = left_y + (bar_width * @bar_spacing)
85
+
86
+ top_x = 0
87
+ stacked_bars.each do |bar|
88
+ next if bar.point == 0
89
+
90
+ bottom_x, = conversion.get_top_bottom_scaled(total)
91
+ bottom_x += @segment_spacing
92
+ top_x, = conversion.get_top_bottom_scaled(total + bar.point)
93
+
94
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
95
+ rect_renderer.render(bottom_x, left_y, top_x, right_y)
96
+
97
+ total += bar.point
114
98
  end
115
- end
116
99
 
117
- if @show_labels_for_bar_values
118
- stack_bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
119
- draw_value_label(x, y, text)
100
+ label_center = left_y + (bar_width / 2.0)
101
+ draw_label(label_center, stacked_index)
102
+
103
+ if @show_labels_for_bar_values
104
+ bar_value_label = Gruff::BarValueLabel::SideBar.new([@graph_left, left_y, top_x, right_y], stacked_bars.sum(&:value))
105
+ bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
106
+ draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
107
+ end
120
108
  end
121
109
  end
122
110
  end