gruff 0.13.0-java → 0.16.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +79 -0
  3. data/.rubocop.yml +29 -31
  4. data/CHANGELOG.md +43 -0
  5. data/README.md +11 -5
  6. data/gruff.gemspec +8 -10
  7. data/lib/gruff/accumulator_bar.rb +4 -2
  8. data/lib/gruff/area.rb +9 -12
  9. data/lib/gruff/bar.rb +46 -31
  10. data/lib/gruff/base.rb +236 -207
  11. data/lib/gruff/bezier.rb +6 -8
  12. data/lib/gruff/box_plot.rb +174 -0
  13. data/lib/gruff/bullet.rb +17 -16
  14. data/lib/gruff/candlestick.rb +112 -0
  15. data/lib/gruff/dot.rb +14 -14
  16. data/lib/gruff/font.rb +42 -0
  17. data/lib/gruff/helper/bar_conversion.rb +5 -5
  18. data/lib/gruff/helper/bar_value_label.rb +26 -20
  19. data/lib/gruff/helper/stacked_mixin.rb +4 -3
  20. data/lib/gruff/histogram.rb +9 -7
  21. data/lib/gruff/line.rb +96 -83
  22. data/lib/gruff/mini/bar.rb +9 -6
  23. data/lib/gruff/mini/legend.rb +16 -12
  24. data/lib/gruff/mini/pie.rb +9 -6
  25. data/lib/gruff/mini/side_bar.rb +9 -6
  26. data/lib/gruff/net.rb +16 -22
  27. data/lib/gruff/patch/rmagick.rb +0 -1
  28. data/lib/gruff/patch/string.rb +2 -1
  29. data/lib/gruff/pie.rb +42 -75
  30. data/lib/gruff/renderer/bezier.rb +8 -9
  31. data/lib/gruff/renderer/circle.rb +8 -9
  32. data/lib/gruff/renderer/dash_line.rb +10 -10
  33. data/lib/gruff/renderer/dot.rb +15 -14
  34. data/lib/gruff/renderer/ellipse.rb +8 -9
  35. data/lib/gruff/renderer/line.rb +8 -11
  36. data/lib/gruff/renderer/polygon.rb +9 -10
  37. data/lib/gruff/renderer/polyline.rb +8 -9
  38. data/lib/gruff/renderer/rectangle.rb +11 -8
  39. data/lib/gruff/renderer/renderer.rb +25 -40
  40. data/lib/gruff/renderer/text.rb +21 -37
  41. data/lib/gruff/scatter.rb +86 -85
  42. data/lib/gruff/side_bar.rb +50 -37
  43. data/lib/gruff/side_stacked_bar.rb +26 -35
  44. data/lib/gruff/spider.rb +52 -28
  45. data/lib/gruff/stacked_area.rb +20 -16
  46. data/lib/gruff/stacked_bar.rb +44 -22
  47. data/lib/gruff/store/store.rb +6 -10
  48. data/lib/gruff/store/xy_data.rb +2 -0
  49. data/lib/gruff/themes.rb +6 -6
  50. data/lib/gruff/version.rb +1 -1
  51. data/lib/gruff.rb +70 -57
  52. data/rails_generators/gruff/templates/controller.rb +1 -1
  53. metadata +15 -32
  54. data/.rubocop_todo.yml +0 -182
  55. data/.travis.yml +0 -23
  56. data/assets/plastik/blue.png +0 -0
  57. data/assets/plastik/green.png +0 -0
  58. data/assets/plastik/red.png +0 -0
  59. data/lib/gruff/photo_bar.rb +0 -93
  60. data/lib/gruff/scene.rb +0 -198
  61. data/lib/gruff/store/custom_data.rb +0 -36
@@ -5,12 +5,10 @@ module Gruff
5
5
  class Renderer::Text
6
6
  using Magick::GruffAnnotate
7
7
 
8
- def initialize(text, font:, size:, color:, weight: Magick::NormalWeight, rotation: nil)
8
+ def initialize(renderer, text, font:, rotation: nil)
9
+ @renderer = renderer
9
10
  @text = text.to_s
10
11
  @font = font
11
- @font_size = size
12
- @font_color = color
13
- @font_weight = weight
14
12
  @rotation = rotation
15
13
  end
16
14
 
@@ -23,50 +21,36 @@ module Gruff
23
21
  @y = y
24
22
  @gravity = gravity
25
23
 
26
- Renderer.instance.text_renderers << self
24
+ @renderer.text_renderers << self
27
25
  end
28
26
 
29
27
  def render(width, height, x, y, gravity = Magick::NorthGravity)
30
- draw = Renderer.instance.draw
31
- image = Renderer.instance.image
32
- scale = Renderer.instance.scale
33
-
34
- draw.rotation = @rotation if @rotation
35
- draw.fill = @font_color
36
- draw.stroke = 'transparent'
37
- draw.font = @font || Renderer::Text.default_font(@font_weight)
38
- draw.font_weight = @font_weight
39
- draw.pointsize = @font_size * scale
40
- draw.gravity = gravity
41
- draw.annotate_scaled(image,
42
- width, height,
43
- x, y,
44
- @text, scale)
45
- draw.rotation = -@rotation if @rotation
28
+ @renderer.draw.rotation = @rotation if @rotation
29
+ @renderer.draw.fill = @font.color
30
+ @renderer.draw.stroke = 'transparent'
31
+ @renderer.draw.font = @font.file_path
32
+ @renderer.draw.font_weight = @font.weight
33
+ @renderer.draw.pointsize = @font.size * @renderer.scale
34
+ @renderer.draw.gravity = gravity
35
+ @renderer.draw.annotate_scaled(@renderer.image,
36
+ width, height,
37
+ x, y,
38
+ @text, @renderer.scale)
39
+ @renderer.draw.rotation = -@rotation if @rotation
46
40
  end
47
41
 
48
- def self.metrics(text, font, size, font_weight = Magick::NormalWeight)
49
- draw = Renderer.instance.draw
50
- image = Renderer.instance.image
51
-
52
- draw.font = font || Renderer::Text.default_font(font_weight)
53
- draw.font_weight = font_weight
54
- draw.pointsize = size
42
+ def metrics
43
+ @renderer.draw.font = @font.file_path
44
+ @renderer.draw.font_weight = @font.weight
45
+ @renderer.draw.pointsize = @font.size
55
46
 
56
47
  # The old ImageMagick causes SEGV with string which has '%' + alphabet (eg. '%S').
57
48
  # This format is used to embed value into a string using image properties.
58
49
  # However, gruff use plain image as canvas which does not have any property.
59
50
  # So, in here, it just escape % in order to avoid SEGV.
60
- text = text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
61
-
62
- draw.get_type_metrics(image, text)
63
- end
64
-
65
- FONT_BOLD = File.expand_path(File.join(__FILE__, '../../../../assets/fonts/Roboto-Bold.ttf'))
66
- FONT_REGULAR = File.expand_path(File.join(__FILE__, '../../../../assets/fonts/Roboto-Regular.ttf'))
51
+ text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
67
52
 
68
- def self.default_font(font_weight)
69
- (font_weight == Magick::BoldWeight) ? FONT_BOLD : FONT_REGULAR
53
+ @renderer.draw.get_type_metrics(@renderer.image, text)
70
54
  end
71
55
  end
72
56
  end
data/lib/gruff/scatter.rb CHANGED
@@ -35,27 +35,6 @@ class Gruff::Scatter < Gruff::Base
35
35
  attr_writer :x_label_margin
36
36
  attr_writer :use_vertical_x_labels
37
37
 
38
- def initialize_store
39
- @store = Gruff::Store.new(Gruff::Store::XYData)
40
- end
41
- private :initialize_store
42
-
43
- def initialize_ivars
44
- super
45
-
46
- @baseline_x_color = @baseline_y_color = 'red'
47
- @baseline_x_value = @baseline_y_value = nil
48
- @circle_radius = nil
49
- @disable_significant_rounding_x_axis = false
50
- @show_vertical_markers = false
51
- @marker_x_count = nil
52
- @maximum_x_value = @minimum_x_value = nil
53
- @stroke_width = nil
54
- @use_vertical_x_labels = false
55
- @x_label_margin = nil
56
- end
57
- private :initialize_ivars
58
-
59
38
  # Allow enabling vertical lines. When you have a lot of data, they can work great.
60
39
  # @deprecated Please use +show_vertical_markers+ attribute instead.
61
40
  def enable_vertical_line_markers=(value)
@@ -63,28 +42,6 @@ class Gruff::Scatter < Gruff::Base
63
42
  @show_vertical_markers = value
64
43
  end
65
44
 
66
- def draw
67
- super
68
- return unless data_given?
69
-
70
- # Check to see if more than one datapoint was given. NaN can result otherwise.
71
- @x_increment = (@x_spread > 1) ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
72
-
73
- store.norm_data.each do |data_row|
74
- data_row.coordinates.each do |x_value, y_value|
75
- next if y_value.nil? || x_value.nil?
76
-
77
- new_x = get_x_coord(x_value, @graph_width, @graph_left)
78
- new_y = @graph_top + (@graph_height - y_value * @graph_height)
79
-
80
- # Reset each time to avoid thin-line errors
81
- stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
82
- circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
83
- Gruff::Renderer::Circle.new(color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
84
- end
85
- end
86
- end
87
-
88
45
  # The first parameter is the name of the dataset. The next two are the
89
46
  # x and y axis data points contain in their own array in that respective
90
47
  # order. The final parameter is the color.
@@ -138,22 +95,59 @@ class Gruff::Scatter < Gruff::Base
138
95
 
139
96
  private
140
97
 
141
- def setup_data
142
- # Update the global min/max values for the x data
143
- @maximum_x_value ||= store.max_x
144
- @minimum_x_value ||= store.min_x
98
+ def initialize_store
99
+ @store = Gruff::Store.new(Gruff::Store::XYData)
100
+ end
145
101
 
102
+ def initialize_attributes
146
103
  super
104
+
105
+ @baseline_x_color = @baseline_y_color = 'red'
106
+ @baseline_x_value = @baseline_y_value = nil
107
+ @circle_radius = nil
108
+ @disable_significant_rounding_x_axis = false
109
+ @show_vertical_markers = false
110
+ @marker_x_count = nil
111
+ @maximum_x_value = @minimum_x_value = nil
112
+ @stroke_width = nil
113
+ @use_vertical_x_labels = false
114
+ @x_label_margin = nil
115
+ end
116
+
117
+ def draw_graph
118
+ store.norm_data.each do |data_row|
119
+ data_row.coordinates.each do |x_value, y_value|
120
+ next if y_value.nil? || x_value.nil?
121
+
122
+ new_x = get_x_coord(x_value, @graph_width, @graph_left)
123
+ new_y = @graph_top + (@graph_height - (y_value * @graph_height))
124
+
125
+ # Reset each time to avoid thin-line errors
126
+ stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
127
+ circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
128
+ Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
129
+ end
130
+ end
147
131
  end
148
132
 
149
- def setup_drawing
133
+ def setup_data
150
134
  # TODO: Need to get x-axis labels working. Current behavior will be to not allow.
151
135
  @labels = {}
152
136
 
137
+ # Update the global min/max values for the x data
138
+ @maximum_x_value = (@maximum_x_value || store.max_x).to_f
139
+ @minimum_x_value = (@minimum_x_value || store.min_x).to_f
140
+
141
+ if @x_axis_increment
142
+ # TODO: Make this work for negative values
143
+ @maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment.to_f].max
144
+ @minimum_x_value = @minimum_x_value.floor
145
+ end
146
+
153
147
  super
154
148
  end
155
149
 
156
- def calculate_spread #:nodoc:
150
+ def calculate_spread
157
151
  super
158
152
  @x_spread = @maximum_x_value.to_f - @minimum_x_value.to_f
159
153
  @x_spread = @x_spread > 0 ? @x_spread : 1
@@ -170,57 +164,64 @@ private
170
164
  super
171
165
  return if @hide_line_markers
172
166
 
173
- if @x_axis_increment.nil?
174
- # TODO: Do the same for larger numbers...100, 75, 50, 25
175
- if @marker_x_count.nil?
176
- (3..7).each do |lines|
177
- if @x_spread % lines == 0.0
178
- @marker_x_count = lines
179
- break
180
- end
181
- end
182
- @marker_x_count ||= 4
183
- end
184
- @x_increment = (@x_spread > 0) ? (@x_spread / @marker_x_count) : 1
185
- unless @disable_significant_rounding_x_axis
186
- @x_increment = significant(@x_increment)
187
- end
188
- else
189
- # TODO: Make this work for negative values
190
- @maximum_x_value = [maximum_value.ceil, @x_axis_increment].max
191
- @minimum_x_value = @minimum_x_value.floor
192
- calculate_spread
193
- normalize
194
-
195
- @marker_x_count = (@x_spread / @x_axis_increment).to_i
196
- @x_increment = @x_axis_increment
197
- end
198
- increment_x_scaled = @graph_width.to_f / (@x_spread / @x_increment)
167
+ increment_x_scaled = @graph_width / (@x_spread / x_increment)
199
168
 
200
169
  # Draw vertical line markers and annotate with numbers
201
- (0..@marker_x_count).each do |index|
170
+ (0..marker_x_count).each do |index|
202
171
  # TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
203
172
  if @show_vertical_markers
204
- x = @graph_left + @graph_width - index.to_f * increment_x_scaled
173
+ x = @graph_left + @graph_width - (index * increment_x_scaled)
205
174
 
206
- line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
207
- line_renderer.render(x, @graph_top, x, @graph_bottom)
175
+ Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_top, x, @graph_bottom)
176
+ Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x, @graph_top + 1, x, @graph_bottom + 1) if @marker_shadow_color
208
177
  end
209
178
 
210
179
  unless @hide_line_numbers
211
- marker_label = BigDecimal(index.to_s) * BigDecimal(@x_increment.to_s) + BigDecimal(@minimum_x_value.to_s)
180
+ marker_label = (BigDecimal(index.to_s) * BigDecimal(x_increment.to_s)) + BigDecimal(@minimum_x_value.to_s)
212
181
  y_offset = @graph_bottom + (@x_label_margin || LABEL_MARGIN)
213
- x_offset = get_x_coord(index.to_f, increment_x_scaled, @graph_left)
182
+ x_offset = get_x_coord(index, increment_x_scaled, @graph_left)
214
183
 
215
- label = x_axis_label(marker_label, @x_increment)
184
+ label = x_axis_label(marker_label, x_increment)
216
185
  rotation = -90.0 if @use_vertical_x_labels
217
- text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color, rotation: rotation)
186
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font, rotation: rotation)
218
187
  text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
219
188
  end
220
189
  end
221
190
  end
222
191
 
223
- def get_x_coord(x_data_point, width, offset) #:nodoc:
224
- x_data_point * width + offset
192
+ def get_x_coord(x_data_point, width, offset)
193
+ (x_data_point * width) + offset
194
+ end
195
+
196
+ def marker_x_count
197
+ # TODO: Do the same for larger numbers...100, 75, 50, 25
198
+ @marker_x_count ||= begin
199
+ if @x_axis_increment.nil?
200
+ count = nil
201
+ (3..7).each do |lines|
202
+ if @x_spread % lines == 0.0
203
+ count = lines and break
204
+ end
205
+ end
206
+ count || 4
207
+ else
208
+ (@x_spread / @x_axis_increment).to_i
209
+ end
210
+ end
211
+ end
212
+
213
+ def x_increment
214
+ @x_increment ||= begin
215
+ if @x_axis_increment.nil?
216
+ increment = @x_spread > 0 ? (@x_spread / marker_x_count) : 1
217
+ unless @disable_significant_rounding_x_axis
218
+ increment = significant(increment)
219
+ end
220
+ else
221
+ increment = @x_axis_increment
222
+ end
223
+
224
+ increment
225
+ end
225
226
  end
226
227
  end
@@ -36,23 +36,13 @@ class Gruff::SideBar < Gruff::Base
36
36
  # Prevent drawing of column labels left of a side bar graph. Default is +false+.
37
37
  attr_writer :hide_labels
38
38
 
39
- def initialize_ivars
40
- super
41
- @bar_spacing = 0.9
42
- @group_spacing = 10
43
- @label_formatting = nil
44
- @show_labels_for_bar_values = false
45
- @hide_labels = false
46
- end
47
- private :initialize_ivars
39
+ # Value to avoid completely overwriting the coordinate axis
40
+ AXIS_MARGIN = 0.5
41
+ private_constant :AXIS_MARGIN
48
42
 
49
- def draw
50
- @has_left_labels = true
43
+ def initialize(*)
51
44
  super
52
-
53
- return unless data_given?
54
-
55
- draw_bars
45
+ @has_left_labels = true
56
46
  end
57
47
 
58
48
  # With Side Bars use the data label for the marker value to the left of the bar.
@@ -61,29 +51,55 @@ class Gruff::SideBar < Gruff::Base
61
51
  warn '#use_data_label is deprecated. It is no longer effective.'
62
52
  end
63
53
 
64
- protected
54
+ private
55
+
56
+ def initialize_attributes
57
+ super
58
+ @bar_spacing = 0.9
59
+ @group_spacing = 10
60
+ @label_formatting = nil
61
+ @show_labels_for_bar_values = false
62
+ @hide_labels = false
63
+ end
65
64
 
66
65
  def hide_labels?
67
66
  @hide_labels
68
67
  end
69
68
 
70
69
  def hide_left_label_area?
71
- hide_labels?
70
+ hide_labels? && @y_axis_label.nil?
72
71
  end
73
72
 
74
73
  def hide_bottom_label_area?
75
- @hide_line_markers
74
+ @hide_line_markers && @x_axis_label.nil? && @legend_at_bottom == false
76
75
  end
77
76
 
78
- private
77
+ def setup_graph_measurements
78
+ super
79
+ return if @hide_line_markers
79
80
 
80
- # Value to avoid completely overwriting the coordinate axis
81
- AXIS_MARGIN = 0.5
81
+ if @show_labels_for_bar_values
82
+ proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
83
+
84
+ if maximum_value >= 0
85
+ _, metrics = Gruff::BarValueLabel.metrics(maximum_value, @label_formatting, proc_text_metrics)
86
+ @graph_right -= metrics.width
87
+ end
88
+
89
+ if minimum_value < 0
90
+ _, metrics = Gruff::BarValueLabel.metrics(minimum_value, @label_formatting, proc_text_metrics)
91
+ width = metrics.width + LABEL_MARGIN
92
+ @graph_left += width - @graph_left if width > @graph_left
93
+ end
94
+
95
+ @graph_width = @graph_right - @graph_left
96
+ end
97
+ end
82
98
 
83
- def draw_bars
99
+ def draw_graph
84
100
  # Setup spacing.
85
101
  #
86
- bars_width = (@graph_height - calculate_spacing) / column_count.to_f
102
+ bars_width = (@graph_height - calculate_spacing) / column_count
87
103
  bar_width = bars_width / store.length
88
104
  padding = (bar_width * (1 - @bar_spacing)) / 2
89
105
 
@@ -93,32 +109,29 @@ private
93
109
  minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
94
110
  )
95
111
 
96
- # if we're a side stacked bar then we don't need to draw ourself at all
97
- # because sometimes (due to different heights/min/max) you can actually
98
- # see both graphs and it looks like crap
99
- return if is_a?(Gruff::SideStackedBar)
112
+ proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
100
113
 
101
114
  store.norm_data.each_with_index do |data_row, row_index|
102
115
  data_row.points.each_with_index do |data_point, point_index|
103
116
  group_spacing = @group_spacing * @scale * point_index
104
117
 
105
118
  left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
106
- right_y = left_y + bar_width * @bar_spacing
119
+ right_y = left_y + (bar_width * @bar_spacing)
107
120
 
108
121
  left_x, right_x = conversion.get_top_bottom_scaled(data_point).sort
109
122
 
110
- rect_renderer = Gruff::Renderer::Rectangle.new(color: data_row.color)
123
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
111
124
  rect_renderer.render(left_x + AXIS_MARGIN, left_y, right_x + AXIS_MARGIN, right_y)
112
125
 
113
126
  # Calculate center based on bar_width and current row
114
- label_center = left_y + bars_width / 2
127
+ label_center = left_y + (bars_width / 2.0)
115
128
 
116
129
  # Subtract half a bar width to center left if requested
117
130
  draw_label(label_center, point_index)
118
131
  if @show_labels_for_bar_values
119
132
  bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
120
- bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
121
- draw_value_label(x, y, text, true)
133
+ bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
134
+ draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
122
135
  end
123
136
  end
124
137
  end
@@ -134,19 +147,19 @@ private
134
147
  number_of_lines = 1 if number_of_lines == 0
135
148
 
136
149
  # TODO: Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
137
- increment = significant(@spread.to_f / number_of_lines)
150
+ increment = significant(@spread / number_of_lines)
138
151
  (0..number_of_lines).each do |index|
139
152
  line_diff = (@graph_right - @graph_left) / number_of_lines
140
153
  x = @graph_right - (line_diff * index) - 1
141
154
 
142
- line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
143
- line_renderer.render(x, @graph_bottom, x, @graph_top)
155
+ Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
156
+ Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x, @graph_bottom + 1, x, @graph_top + 1) if @marker_shadow_color
144
157
 
145
158
  unless @hide_line_numbers
146
159
  diff = index - number_of_lines
147
- 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)
148
161
  label = x_axis_label(marker_label, @increment)
149
- text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color)
162
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
150
163
  text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + LABEL_MARGIN, Magick::CenterGravity)
151
164
  end
152
165
  end
@@ -39,86 +39,77 @@ class Gruff::SideStackedBar < Gruff::SideBar
39
39
  # Prevent drawing of column labels left of a side stacked bar graph. Default is +false+.
40
40
  attr_writer :hide_labels
41
41
 
42
- def initialize_ivars
42
+ def initialize(*)
43
+ super
44
+ @has_left_labels = true
45
+ end
46
+
47
+ private
48
+
49
+ def initialize_attributes
43
50
  super
44
51
  @bar_spacing = 0.9
45
52
  @segment_spacing = 2.0
46
53
  @label_formatting = nil
47
54
  @show_labels_for_bar_values = false
48
55
  @hide_labels = false
56
+ @minimum_value = 0.0
49
57
  end
50
- private :initialize_ivars
51
58
 
52
- def draw
53
- @has_left_labels = true
59
+ def setup_data
54
60
  calculate_maximum_by_stack
55
61
  super
56
62
  end
57
63
 
58
- protected
59
-
60
- def hide_labels?
61
- @hide_labels
62
- end
63
-
64
- def hide_left_label_area?
65
- hide_labels?
66
- end
67
-
68
- def hide_bottom_label_area?
69
- @hide_line_markers
70
- end
71
-
72
- private
73
-
74
- def draw_bars
64
+ def draw_graph
75
65
  # Setup spacing.
76
66
  #
77
67
  # Columns sit stacked.
78
- bar_width = @graph_height / column_count.to_f
68
+ bar_width = @graph_height / column_count
79
69
  height = Array.new(column_count, 0)
80
70
  length = Array.new(column_count, @graph_left)
81
71
  padding = (bar_width * (1 - @bar_spacing)) / 2
82
- stack_bar_value_label = Gruff::BarValueLabel::StackedBar.new
72
+ stack_bar_value_labels = Gruff::BarValueLabel::StackedBar.new
83
73
 
84
74
  store.norm_data.each_with_index do |data_row, row_index|
85
75
  data_row.points.each_with_index do |data_point, point_index|
86
76
  ## using the original calculations from the stacked bar chart to get the difference between
87
77
  ## part of the bart chart we wish to stack.
88
- temp1 = @graph_left + (@graph_width -
89
- data_point * @graph_width -
90
- height[point_index]) + 1
91
- temp2 = @graph_left + @graph_width - height[point_index] - 1
78
+ temp1 = @graph_left + (@graph_width - (data_point * @graph_width) - height[point_index])
79
+ temp2 = @graph_left + @graph_width - height[point_index]
92
80
  difference = temp2 - temp1
81
+ difference = 0 if difference < 0
93
82
 
94
83
  left_x = length[point_index]
95
84
  left_y = @graph_top + (bar_width * point_index) + padding
96
- right_x = left_x + difference - @segment_spacing
97
- right_y = left_y + bar_width * @bar_spacing
85
+ right_x = left_x + difference
86
+ right_x -= @segment_spacing if row_index != store.columns - 1
87
+ right_y = left_y + (bar_width * @bar_spacing)
98
88
  length[point_index] += difference
99
- height[point_index] += (data_point * @graph_width - 2)
89
+ height[point_index] += (data_point * @graph_width)
100
90
 
101
91
  bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
102
- stack_bar_value_label.add(bar_value_label, point_index)
92
+ stack_bar_value_labels.add(bar_value_label, point_index)
103
93
 
104
94
  # if a data point is 0 it can result in weird really thing lines
105
95
  # that shouldn't even be there being drawn on top of the existing
106
96
  # bar - this is bad
107
97
  if data_point != 0
108
- rect_renderer = Gruff::Renderer::Rectangle.new(color: data_row.color)
98
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
109
99
  rect_renderer.render(left_x, left_y, right_x, right_y)
110
100
  # Calculate center based on bar_width and current row
111
101
  end
112
102
  # we still need to draw the labels
113
103
  # Calculate center based on bar_width and current row
114
- label_center = left_y + bar_width / 2
104
+ label_center = left_y + (bar_width / 2.0)
115
105
  draw_label(label_center, point_index)
116
106
  end
117
107
  end
118
108
 
119
109
  if @show_labels_for_bar_values
120
- stack_bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
121
- draw_value_label(x, y, text, true)
110
+ proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
111
+ stack_bar_value_labels.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
112
+ draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
122
113
  end
123
114
  end
124
115
  end