gruff 0.13.0-java → 0.16.0-java

Sign up to get free protection for your applications and to get access to all the features.
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