gruff 0.12.2 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +66 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +34 -27
  5. data/CHANGELOG.md +29 -0
  6. data/README.md +15 -7
  7. data/assets/fonts/LICENSE.txt +202 -0
  8. data/assets/fonts/Roboto-Bold.ttf +0 -0
  9. data/assets/fonts/Roboto-Regular.ttf +0 -0
  10. data/gruff.gemspec +9 -10
  11. data/lib/gruff/accumulator_bar.rb +3 -1
  12. data/lib/gruff/area.rb +5 -8
  13. data/lib/gruff/bar.rb +32 -49
  14. data/lib/gruff/base.rb +199 -115
  15. data/lib/gruff/bezier.rb +4 -6
  16. data/lib/gruff/bullet.rb +12 -11
  17. data/lib/gruff/dot.rb +13 -14
  18. data/lib/gruff/font.rb +39 -0
  19. data/lib/gruff/helper/bar_conversion.rb +27 -12
  20. data/lib/gruff/helper/bar_value_label.rb +71 -0
  21. data/lib/gruff/helper/stacked_mixin.rb +1 -2
  22. data/lib/gruff/histogram.rb +9 -7
  23. data/lib/gruff/line.rb +57 -50
  24. data/lib/gruff/mini/bar.rb +9 -6
  25. data/lib/gruff/mini/legend.rb +12 -8
  26. data/lib/gruff/mini/pie.rb +9 -6
  27. data/lib/gruff/mini/side_bar.rb +9 -6
  28. data/lib/gruff/net.rb +9 -15
  29. data/lib/gruff/patch/rmagick.rb +0 -1
  30. data/lib/gruff/patch/string.rb +1 -1
  31. data/lib/gruff/pie.rb +23 -65
  32. data/lib/gruff/renderer/bezier.rb +8 -9
  33. data/lib/gruff/renderer/circle.rb +8 -9
  34. data/lib/gruff/renderer/dash_line.rb +9 -10
  35. data/lib/gruff/renderer/dot.rb +13 -14
  36. data/lib/gruff/renderer/ellipse.rb +8 -9
  37. data/lib/gruff/renderer/line.rb +8 -9
  38. data/lib/gruff/renderer/polygon.rb +9 -10
  39. data/lib/gruff/renderer/polyline.rb +8 -9
  40. data/lib/gruff/renderer/rectangle.rb +7 -8
  41. data/lib/gruff/renderer/renderer.rb +25 -40
  42. data/lib/gruff/renderer/text.rb +21 -29
  43. data/lib/gruff/scatter.rb +55 -75
  44. data/lib/gruff/scene.rb +28 -18
  45. data/lib/gruff/side_bar.rb +35 -54
  46. data/lib/gruff/side_stacked_bar.rb +14 -17
  47. data/lib/gruff/spider.rb +11 -20
  48. data/lib/gruff/stacked_area.rb +10 -11
  49. data/lib/gruff/stacked_bar.rb +14 -15
  50. data/lib/gruff/store/store.rb +6 -10
  51. data/lib/gruff/store/xy_data.rb +2 -0
  52. data/lib/gruff/themes.rb +6 -6
  53. data/lib/gruff/version.rb +1 -1
  54. data/lib/gruff.rb +68 -55
  55. data/rails_generators/gruff/templates/controller.rb +1 -1
  56. metadata +34 -20
  57. data/.rubocop_todo.yml +0 -190
  58. data/.travis.yml +0 -23
  59. data/assets/plastik/blue.png +0 -0
  60. data/assets/plastik/green.png +0 -0
  61. data/assets/plastik/red.png +0 -0
  62. data/lib/gruff/helper/bar_value_label_mixin.rb +0 -33
  63. data/lib/gruff/photo_bar.rb +0 -93
data/lib/gruff/base.rb CHANGED
@@ -93,15 +93,6 @@ module Gruff
93
93
  # Set the large title of the graph displayed at the top.
94
94
  attr_writer :title
95
95
 
96
- # Same as {#font=} but for the title.
97
- attr_writer :title_font
98
-
99
- # Specifies whether to draw the title bolded or not. Default is +true+.
100
- attr_writer :bold_title
101
-
102
- # Specifies the text color.
103
- attr_writer :font_color
104
-
105
96
  # Prevent drawing of line markers. Default is +false+.
106
97
  attr_writer :hide_line_markers
107
98
 
@@ -118,21 +109,9 @@ module Gruff
118
109
  # to +"No Data."+.
119
110
  attr_writer :no_data_message
120
111
 
121
- # Set the font size of the large title at the top of the graph. Default is +36+.
122
- attr_writer :title_font_size
123
-
124
- # Optionally set the size of the font. Based on an 800x600px graph.
125
- # Default is +20+.
126
- #
127
- # Will be scaled down if the graph is smaller than 800px wide.
128
- attr_writer :legend_font_size
129
-
130
112
  # Display the legend under the graph. Default is +false+.
131
113
  attr_writer :legend_at_bottom
132
114
 
133
- # The font size of the labels around the graph. Default is +21+.
134
- attr_writer :marker_font_size
135
-
136
115
  # Set the color of the auxiliary lines.
137
116
  attr_writer :marker_color
138
117
 
@@ -156,9 +135,11 @@ module Gruff
156
135
  # Will be scaled down if graph is smaller than 800px wide.
157
136
  attr_writer :legend_box_size
158
137
 
159
- # With Side Bars use the data label for the marker value to the left of the bar.
160
- # Default is +false+.
161
- attr_writer :use_data_label
138
+ # Allow passing lambdas to format labels for x axis.
139
+ attr_writer :x_axis_label_format
140
+
141
+ # Allow passing lambdas to format labels for y axis.
142
+ attr_writer :y_axis_label_format
162
143
 
163
144
  # If one numerical argument is given, the graph is drawn at 4/3 ratio
164
145
  # according to the given width (+800+ results in 800x600, +400+ gives 400x300,
@@ -179,7 +160,7 @@ module Gruff
179
160
  @rows.freeze
180
161
 
181
162
  initialize_graph_scale
182
- initialize_ivars
163
+ initialize_attributes
183
164
  initialize_store
184
165
 
185
166
  self.theme = Themes::KEYNOTE
@@ -207,21 +188,17 @@ module Gruff
207
188
  #
208
189
  # This makes it possible to set defaults in a subclass but still allow
209
190
  # developers to change this values in their program.
210
- def initialize_ivars
191
+ def initialize_attributes
211
192
  @marker_count = nil
212
193
  @maximum_value = @minimum_value = nil
213
194
  @labels = {}
214
195
  @sort = false
215
196
  @sorted_drawing = false
216
197
  @title = nil
217
- @title_font = nil
218
-
219
- @font = nil
220
- @bold_title = true
221
198
 
222
- @marker_font_size = 21.0
223
- @legend_font_size = 20.0
224
- @title_font_size = 36.0
199
+ @title_font = Gruff::Font.new(size: 36.0, bold: true)
200
+ @marker_font = Gruff::Font.new(size: 21.0)
201
+ @legend_font = Gruff::Font.new(size: 20.0)
225
202
 
226
203
  @top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
227
204
  @legend_margin = LEGEND_MARGIN
@@ -238,12 +215,14 @@ module Gruff
238
215
  @label_max_size = 0
239
216
  @label_truncation_style = :absolute
240
217
 
241
- @use_data_label = false
242
218
  @x_axis_increment = nil
243
219
  @x_axis_label = @y_axis_label = nil
244
220
  @y_axis_increment = nil
221
+
222
+ @x_axis_label_format = nil
223
+ @y_axis_label_format = nil
245
224
  end
246
- protected :initialize_ivars
225
+ protected :initialize_attributes
247
226
 
248
227
  # Sets the top, bottom, left and right margins to +margin+.
249
228
  #
@@ -258,8 +237,62 @@ module Gruff
258
237
  # @param font_path [String] The path to font.
259
238
  #
260
239
  def font=(font_path)
261
- @font = font_path
262
- Gruff::Renderer.font = @font
240
+ @title_font.path = font_path unless @title_font.path
241
+ @marker_font.path = font_path
242
+ @legend_font.path = font_path
243
+ end
244
+
245
+ # Same as {#font=} but for the title.
246
+ #
247
+ # @param font_path [String] The path to font.
248
+ #
249
+ def title_font=(font_path)
250
+ @title_font.path = font_path
251
+ end
252
+
253
+ # Set the font size of the large title at the top of the graph. Default is +36+.
254
+ #
255
+ # @param value [Numeric] title font size
256
+ #
257
+ def title_font_size=(value)
258
+ @title_font.size = value
259
+ end
260
+
261
+ # The font size of the labels around the graph. Default is +21+.
262
+ #
263
+ # @param value [Numeric] marker font size
264
+ #
265
+ def marker_font_size=(value)
266
+ @marker_font.size = value
267
+ end
268
+
269
+ # Optionally set the size of the font. Based on an 800x600px graph.
270
+ # Default is +20+.
271
+ #
272
+ # Will be scaled down if the graph is smaller than 800px wide.
273
+ #
274
+ # @param value [Numeric] legend font size
275
+ #
276
+ def legend_font_size=(value)
277
+ @legend_font.size = value
278
+ end
279
+
280
+ # Specifies whether to draw the title bolded or not. Default is +true+.
281
+ #
282
+ # @param value [Boolean] specifies whether to draw the title bolded or not.
283
+ #
284
+ def bold_title=(value)
285
+ @title_font.bold = value
286
+ end
287
+
288
+ # Specifies the text color.
289
+ #
290
+ # @param value [String] color
291
+ #
292
+ def font_color=(value)
293
+ @title_font.color = value
294
+ @marker_font.color = value
295
+ @legend_font.color = value
263
296
  end
264
297
 
265
298
  # Add a color to the list of available colors for lines.
@@ -328,12 +361,13 @@ module Gruff
328
361
  }
329
362
  @theme_options = defaults.merge options
330
363
 
364
+ self.marker_color = @theme_options[:marker_color]
365
+ self.font_color = @theme_options[:font_color] || @marker_color
366
+
331
367
  @colors = @theme_options[:colors]
332
- @marker_color = @theme_options[:marker_color]
333
368
  @marker_shadow_color = @theme_options[:marker_shadow_color]
334
- @font_color = @theme_options[:font_color] || @marker_color
335
369
 
336
- Gruff::Renderer.setup(@columns, @rows, @font, @scale, @theme_options)
370
+ @renderer = Gruff::Renderer.new(@columns, @rows, @scale, @theme_options)
337
371
  end
338
372
 
339
373
  # Apply Apple's keynote theme.
@@ -435,8 +469,8 @@ module Gruff
435
469
  def to_image
436
470
  @to_image ||= begin
437
471
  draw
438
- Gruff::Renderer.finish
439
- Gruff::Renderer.instance.image
472
+ renderer.finish
473
+ renderer.image
440
474
  end
441
475
  end
442
476
 
@@ -452,27 +486,29 @@ module Gruff
452
486
  end
453
487
  end
454
488
 
455
- protected
456
-
457
- # Overridden by subclasses to do the actual plotting of the graph.
458
- #
459
- # Subclasses should start by calling super() for this method.
489
+ # Draw a graph.
460
490
  def draw
491
+ setup_data
492
+
461
493
  # Maybe should be done in one of the following functions for more granularity.
462
494
  unless data_given?
463
495
  draw_no_data
464
496
  return
465
497
  end
466
498
 
467
- setup_data
468
499
  setup_drawing
469
500
 
470
501
  draw_legend
471
502
  draw_line_markers
472
503
  draw_axis_labels
473
504
  draw_title
505
+ draw_graph
474
506
  end
475
507
 
508
+ protected
509
+
510
+ attr_reader :renderer
511
+
476
512
  # Perform data manipulation before calculating chart measurements
477
513
  def setup_data # :nodoc:
478
514
  if @y_axis_increment && !@hide_line_markers
@@ -577,13 +613,13 @@ module Gruff
577
613
  x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN + @marker_caps_height
578
614
 
579
615
  # TODO: Center between graph area
580
- text_renderer = Gruff::Renderer::Text.new(@x_axis_label, font: @font, size: @marker_font_size, color: @font_color)
616
+ text_renderer = Gruff::Renderer::Text.new(renderer, @x_axis_label, font: @marker_font)
581
617
  text_renderer.add_to_render_queue(@raw_columns, 1.0, 0.0, x_axis_label_y_coordinate)
582
618
  end
583
619
 
584
620
  if @y_axis_label
585
621
  # Y Axis, rotated vertically
586
- text_renderer = Gruff::Renderer::Text.new(@y_axis_label, font: @font, size: @marker_font_size, color: @font_color, rotation: -90)
622
+ text_renderer = Gruff::Renderer::Text.new(renderer, @y_axis_label, font: @marker_font, rotation: -90)
587
623
  text_renderer.add_to_render_queue(1.0, @raw_rows, @left_margin + @marker_caps_height / 2.0, 0.0, Magick::CenterGravity)
588
624
  end
589
625
  end
@@ -598,13 +634,13 @@ module Gruff
598
634
  (0..marker_count).each do |index|
599
635
  y = @graph_top + @graph_height - index.to_f * increment_scaled
600
636
 
601
- line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
637
+ line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
602
638
  line_renderer.render(@graph_left, y, @graph_right, y)
603
639
 
604
640
  unless @hide_line_numbers
605
641
  marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
606
- label = label(marker_label, @increment)
607
- text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color)
642
+ label = y_axis_label(marker_label, @increment)
643
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
608
644
  text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y, Magick::EastGravity)
609
645
  end
610
646
  end
@@ -627,7 +663,7 @@ module Gruff
627
663
  current_x_offset = center(label_widths.first.sum)
628
664
  current_y_offset = begin
629
665
  if @legend_at_bottom
630
- @graph_height + @title_margin
666
+ @graph_bottom + @legend_margin + @legend_caps_height + LABEL_MARGIN
631
667
  else
632
668
  hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + @title_caps_height
633
669
  end
@@ -637,17 +673,17 @@ module Gruff
637
673
  next if legend_label.empty?
638
674
 
639
675
  # Draw label
640
- text_renderer = Gruff::Renderer::Text.new(legend_label, font: @font, size: @legend_font_size, color: @font_color)
676
+ text_renderer = Gruff::Renderer::Text.new(renderer, legend_label, font: @legend_font)
641
677
  text_renderer.add_to_render_queue(@raw_columns, 1.0, current_x_offset + (legend_square_width * 1.7), current_y_offset, Magick::WestGravity)
642
678
 
643
679
  # Now draw box with color of this dataset
644
- rect_renderer = Gruff::Renderer::Rectangle.new(color: store.data[index].color)
680
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
645
681
  rect_renderer.render(current_x_offset,
646
682
  current_y_offset - legend_square_width / 2.0,
647
683
  current_x_offset + legend_square_width,
648
684
  current_y_offset + legend_square_width / 2.0)
649
685
 
650
- width = calculate_width(@legend_font_size, legend_label)
686
+ width = calculate_width(@legend_font, legend_label)
651
687
  current_x_offset += width + (legend_square_width * 2.7)
652
688
  label_widths.first.shift
653
689
 
@@ -659,8 +695,6 @@ module Gruff
659
695
  unless label_widths.empty?
660
696
  # Wrap to next line and shrink available graph dimensions
661
697
  current_y_offset += line_height
662
- @graph_top += line_height
663
- @graph_height = @graph_bottom - @graph_top
664
698
  end
665
699
  end
666
700
  end
@@ -670,15 +704,12 @@ module Gruff
670
704
  def draw_title
671
705
  return if hide_title?
672
706
 
673
- font = @title_font || @font
674
- font_weight = @bold_title ? Magick::BoldWeight : Magick::NormalWeight
675
- font_size = @title_font_size
676
-
677
- metrics = Renderer::Text.metrics(@title, font_size, font_weight)
707
+ metrics = Gruff::Renderer::Text.new(renderer, @title, font: @title_font).metrics
678
708
  if metrics.width > @raw_columns
679
- font_size = font_size * (@raw_columns / metrics.width) * 0.95
709
+ @title_font.size = @title_font.size * (@raw_columns / metrics.width) * 0.95
680
710
  end
681
- text_renderer = Gruff::Renderer::Text.new(@title, font: font, size: font_size, color: @font_color, weight: font_weight)
711
+
712
+ text_renderer = Gruff::Renderer::Text.new(renderer, @title, font: @title_font)
682
713
  text_renderer.add_to_render_queue(@raw_columns, 1.0, 0, @top_margin)
683
714
  end
684
715
 
@@ -691,14 +722,11 @@ module Gruff
691
722
 
692
723
  # TESTME
693
724
  # FIXME: Consider chart types other than bar
694
- # TODO: See if index.odd? is the best stragegy
725
+ # TODO: See if index.odd? is the best strategy
695
726
  y_offset += @label_stagger_height if index.odd?
696
727
 
697
- label_text = truncate_label_text(@labels[index].to_s)
698
-
699
728
  if x_offset >= @graph_left && x_offset <= @graph_right
700
- text_renderer = Gruff::Renderer::Text.new(label_text, font: @font, size: @marker_font_size, color: @font_color)
701
- text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset, gravity)
729
+ draw_label_at(1.0, 1.0, x_offset, y_offset, @labels[index], gravity)
702
730
  end
703
731
  end
704
732
  end
@@ -713,20 +741,33 @@ module Gruff
713
741
  end
714
742
  end
715
743
 
744
+ def draw_label_at(width, height, x, y, text, gravity = Magick::NorthGravity)
745
+ label_text = truncate_label_text(text)
746
+ text_renderer = Gruff::Renderer::Text.new(renderer, label_text, font: @marker_font)
747
+ text_renderer.add_to_render_queue(width, height, x, y, gravity)
748
+ end
749
+
716
750
  # Draws the data value over the data point in bar graphs
717
- def draw_value_label(x_offset, y_offset, data_point, bar_value = false)
718
- return if @hide_line_markers && !bar_value
751
+ def draw_value_label(x_offset, y_offset, data_point)
752
+ return if @hide_line_markers
719
753
 
720
- text_renderer = Gruff::Renderer::Text.new(data_point, font: @font, size: @marker_font_size, color: @font_color)
754
+ text_renderer = Gruff::Renderer::Text.new(renderer, data_point, font: @marker_font)
721
755
  text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
722
756
  end
723
757
 
724
758
  # Shows an error message because you have no data.
725
759
  def draw_no_data
726
- text_renderer = Gruff::Renderer::Text.new(@no_data_message, font: @font, size: 80, color: @font_color)
760
+ font = @title_font.dup
761
+ font.size = 80
762
+ font.bold = false
763
+ text_renderer = Gruff::Renderer::Text.new(renderer, @no_data_message, font: font)
727
764
  text_renderer.render(@raw_columns, @raw_rows, 0, 0, Magick::CenterGravity)
728
765
  end
729
766
 
767
+ def draw_graph
768
+ raise 'Should implement this method at inherited class.'
769
+ end
770
+
730
771
  # Resets everything to defaults (except data).
731
772
  def reset_themes
732
773
  @theme_options = {}
@@ -742,7 +783,7 @@ module Gruff
742
783
  end
743
784
 
744
785
  def clip_value_if_greater_than(value, max_value) # :nodoc:
745
- (value > max_value) ? max_value : value
786
+ value > max_value ? max_value : value
746
787
  end
747
788
 
748
789
  def significant(i) # :nodoc:
@@ -789,15 +830,15 @@ module Gruff
789
830
  private
790
831
 
791
832
  def setup_marker_caps_height
792
- hide_bottom_label_area? ? 0 : calculate_caps_height(@marker_font_size)
833
+ hide_bottom_label_area? ? 0 : calculate_caps_height(@marker_font)
793
834
  end
794
835
 
795
836
  def setup_title_caps_height
796
- hide_title? ? 0 : calculate_caps_height(@title_font_size) * @title.lines.to_a.size
837
+ hide_title? ? 0 : calculate_caps_height(@title_font) * @title.lines.to_a.size
797
838
  end
798
839
 
799
840
  def setup_legend_caps_height
800
- @hide_legend ? 0 : calculate_caps_height(@legend_font_size)
841
+ @hide_legend ? 0 : calculate_caps_height(@legend_font)
801
842
  end
802
843
 
803
844
  def graph_right_margin
@@ -808,7 +849,7 @@ module Gruff
808
849
  # Make space for half the width of the rightmost column label.
809
850
  # Might be greater than the number of columns if between-style bar markers are used.
810
851
  last_label = @labels.keys.max.to_i
811
- (last_label >= (column_count - 1) && @center_labels_over_point) ? calculate_width(@marker_font_size, @labels[last_label]) / 2.0 : 0
852
+ last_label >= (column_count - 1) && @center_labels_over_point ? calculate_width(@marker_font, @labels[last_label]) / 2.0 : 0
812
853
  end
813
854
 
814
855
  def setup_left_margin
@@ -816,12 +857,12 @@ module Gruff
816
857
 
817
858
  text = begin
818
859
  if @has_left_labels
819
- @labels.values.reduce('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }
860
+ @labels.values.reduce('') { |value, memo| value.to_s.length > memo.to_s.length ? value : memo }
820
861
  else
821
- label(maximum_value.to_f, @increment)
862
+ y_axis_label(maximum_value.to_f, @increment)
822
863
  end
823
864
  end
824
- longest_left_label_width = calculate_width(@marker_font_size, text)
865
+ longest_left_label_width = calculate_width(@marker_font, truncate_label_text(text))
825
866
  longest_left_label_width *= 1.25 if @has_left_labels
826
867
 
827
868
  # Shift graph if left line numbers are hidden
@@ -831,17 +872,16 @@ module Gruff
831
872
  end
832
873
 
833
874
  def setup_top_margin
834
- return @top_margin if @legend_at_bottom
835
-
836
875
  # When @hide title, leave a title_margin space for aesthetics.
837
876
  # Same with @hide_legend
838
877
  @top_margin +
839
878
  (hide_title? ? @title_margin : @title_caps_height + @title_margin) +
840
- (@hide_legend ? @legend_margin : @legend_caps_height + @legend_margin)
879
+ (@hide_legend || @legend_at_bottom ? @legend_margin : calculate_legend_height + @legend_margin)
841
880
  end
842
881
 
843
882
  def setup_bottom_margin
844
883
  graph_bottom_margin = hide_bottom_label_area? ? @bottom_margin : @bottom_margin + @marker_caps_height + LABEL_MARGIN
884
+ graph_bottom_margin += (calculate_legend_height + @legend_margin) if @legend_at_bottom
845
885
 
846
886
  x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN
847
887
  # FIXME: Consider chart types other than bar
@@ -849,6 +889,7 @@ module Gruff
849
889
  end
850
890
 
851
891
  def truncate_label_text(text)
892
+ text = text.to_s
852
893
  return text if text.size <= @label_max_size
853
894
 
854
895
  if @label_truncation_style == :trailing_dots
@@ -863,40 +904,58 @@ module Gruff
863
904
  # Return a formatted string representing a number value that should be
864
905
  # printed as a label.
865
906
  def label(value, increment)
866
- label = if increment
867
- if increment >= 10 || (increment * 1) == (increment * 1).to_i.to_f
868
- sprintf('%0i', value)
869
- elsif increment >= 1.0 || (increment * 10) == (increment * 10).to_i.to_f
870
- sprintf('%0.1f', value)
871
- elsif increment >= 0.1 || (increment * 100) == (increment * 100).to_i.to_f
872
- sprintf('%0.2f', value)
873
- elsif increment >= 0.01 || (increment * 1000) == (increment * 1000).to_i.to_f
874
- sprintf('%0.3f', value)
875
- elsif increment >= 0.001 || (increment * 10000) == (increment * 10000).to_i.to_f
876
- sprintf('%0.4f', value)
877
- else
878
- value.to_s
879
- end
880
- elsif (@spread.to_f % (marker_count.to_f == 0 ? 1 : marker_count.to_f) == 0) || !@y_axis_increment.nil?
881
- value.to_i.to_s
882
- elsif @spread > 10.0
883
- sprintf('%0i', value)
884
- elsif @spread >= 3.0
885
- sprintf('%0.2f', value)
886
- else
887
- value.to_s
888
- end
907
+ label = begin
908
+ if increment
909
+ if increment >= 10 || (increment * 1) == (increment * 1).to_i.to_f
910
+ sprintf('%0i', value)
911
+ elsif increment >= 1.0 || (increment * 10) == (increment * 10).to_i.to_f
912
+ sprintf('%0.1f', value)
913
+ elsif increment >= 0.1 || (increment * 100) == (increment * 100).to_i.to_f
914
+ sprintf('%0.2f', value)
915
+ elsif increment >= 0.01 || (increment * 1000) == (increment * 1000).to_i.to_f
916
+ sprintf('%0.3f', value)
917
+ elsif increment >= 0.001 || (increment * 10_000) == (increment * 10_000).to_i.to_f
918
+ sprintf('%0.4f', value)
919
+ else
920
+ value.to_s
921
+ end
922
+ elsif (@spread.to_f % (marker_count.to_f == 0 ? 1 : marker_count.to_f) == 0) || !@y_axis_increment.nil?
923
+ value.to_i.to_s
924
+ elsif @spread > 10.0
925
+ sprintf('%0i', value)
926
+ elsif @spread >= 3.0
927
+ sprintf('%0.2f', value)
928
+ else
929
+ value.to_s
930
+ end
931
+ end
889
932
 
890
933
  parts = label.split('.')
891
934
  parts[0] = parts[0].commify
892
935
  parts.join('.')
893
936
  end
894
937
 
938
+ def x_axis_label(value, increment)
939
+ if @x_axis_label_format
940
+ @x_axis_label_format.call(value)
941
+ else
942
+ label(value, increment)
943
+ end
944
+ end
945
+
946
+ def y_axis_label(value, increment)
947
+ if @y_axis_label_format
948
+ @y_axis_label_format.call(value)
949
+ else
950
+ label(value, increment)
951
+ end
952
+ end
953
+
895
954
  def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
896
955
  # May fix legend drawing problem at small sizes
897
956
  label_widths = [[]] # Used to calculate line wrap
898
957
  legend_labels.each do |label|
899
- width = calculate_width(@legend_font_size, label)
958
+ width = calculate_width(@legend_font, label)
900
959
  label_width = width + legend_square_width * 2.7
901
960
  label_widths.last.push label_width
902
961
 
@@ -908,13 +967,38 @@ module Gruff
908
967
  label_widths
909
968
  end
910
969
 
970
+ def calculate_legend_height
971
+ return 0.0 if @hide_legend
972
+
973
+ legend_labels = store.data.map(&:label)
974
+ legend_square_width = @legend_box_size
975
+ label_widths = calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
976
+ legend_height = 0.0
977
+
978
+ legend_labels.each_with_index do |legend_label, _index|
979
+ next if legend_label.empty?
980
+
981
+ label_widths.first.shift
982
+ if label_widths.first.empty?
983
+ label_widths.shift
984
+ line_height = [@legend_caps_height, legend_square_width].max + @legend_margin
985
+ unless label_widths.empty?
986
+ # Wrap to next line and shrink available graph dimensions
987
+ legend_height += line_height
988
+ end
989
+ end
990
+ end
991
+
992
+ legend_height + @legend_caps_height
993
+ end
994
+
911
995
  # Returns the height of the capital letter 'X' for the current font and
912
996
  # size.
913
997
  #
914
998
  # Not scaled since it deals with dimensions that the regular scaling will
915
999
  # handle.
916
- def calculate_caps_height(font_size)
917
- metrics = Renderer::Text.metrics('X', font_size)
1000
+ def calculate_caps_height(font)
1001
+ metrics = Gruff::Renderer::Text.new(renderer, 'X', font: font).metrics
918
1002
  metrics.height
919
1003
  end
920
1004
 
@@ -922,11 +1006,11 @@ module Gruff
922
1006
  #
923
1007
  # Not scaled since it deals with dimensions that the regular
924
1008
  # scaling will handle.
925
- def calculate_width(font_size, text)
1009
+ def calculate_width(font, text)
926
1010
  text = text.to_s
927
1011
  return 0 if text.empty?
928
1012
 
929
- metrics = Renderer::Text.metrics(text, font_size)
1013
+ metrics = Gruff::Renderer::Text.new(renderer, text, font: font).metrics
930
1014
  metrics.width
931
1015
  end
932
1016
 
@@ -935,7 +1019,7 @@ module Gruff
935
1019
  # Try to use a number of horizontal lines that will come out even.
936
1020
  #
937
1021
  # TODO Do the same for larger numbers...100, 75, 50, 25
938
- @increment = (@spread > 0 && marker_count > 0) ? significant(@spread / marker_count) : 1
1022
+ @increment = @spread > 0 && marker_count > 0 ? significant(@spread / marker_count) : 1
939
1023
  else
940
1024
  # TODO: Make this work for negative values
941
1025
  self.marker_count = (@spread / @y_axis_increment).to_i
data/lib/gruff/bezier.rb CHANGED
@@ -19,11 +19,9 @@
19
19
  # g.write('bezier.png')
20
20
  #
21
21
  class Gruff::Bezier < Gruff::Base
22
- def draw
23
- super
24
-
25
- return unless data_given?
22
+ private
26
23
 
24
+ def draw_graph
27
25
  x_increment = @graph_width / (column_count - 1).to_f
28
26
 
29
27
  store.norm_data.each do |data_row|
@@ -48,9 +46,9 @@ class Gruff::Bezier < Gruff::Base
48
46
  stroke_width = clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
49
47
 
50
48
  if RUBY_PLATFORM == 'java'
51
- Gruff::Renderer::Polyline.new(color: data_row.color, width: stroke_width).render(poly_points)
49
+ Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
52
50
  else
53
- Gruff::Renderer::Bezier.new(color: data_row.color, width: stroke_width).render(poly_points)
51
+ Gruff::Renderer::Bezier.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
54
52
  end
55
53
  end
56
54
  end