gruff 0.30.0 → 0.32.0

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3 -3
  3. data/.github/workflows/release.yml +24 -0
  4. data/.rubocop.yml +4 -0
  5. data/.rubocop_todo.yml +0 -6
  6. data/CHANGELOG.md +21 -0
  7. data/lib/gruff/accumulator_bar.rb +1 -0
  8. data/lib/gruff/area.rb +2 -0
  9. data/lib/gruff/bar.rb +5 -5
  10. data/lib/gruff/base.rb +144 -90
  11. data/lib/gruff/bezier.rb +1 -0
  12. data/lib/gruff/box.rb +8 -0
  13. data/lib/gruff/bubble.rb +4 -0
  14. data/lib/gruff/bullet.rb +4 -0
  15. data/lib/gruff/candlestick.rb +17 -5
  16. data/lib/gruff/dot.rb +4 -5
  17. data/lib/gruff/font.rb +2 -0
  18. data/lib/gruff/helper/bar_value_label.rb +2 -0
  19. data/lib/gruff/helper/stacked_mixin.rb +1 -0
  20. data/lib/gruff/histogram.rb +3 -0
  21. data/lib/gruff/line.rb +28 -0
  22. data/lib/gruff/mini/bar.rb +3 -0
  23. data/lib/gruff/mini/legend.rb +13 -2
  24. data/lib/gruff/mini/pie.rb +3 -0
  25. data/lib/gruff/mini/side_bar.rb +3 -0
  26. data/lib/gruff/net.rb +6 -0
  27. data/lib/gruff/patch/rmagick.rb +10 -0
  28. data/lib/gruff/patch/string.rb +2 -0
  29. data/lib/gruff/pie.rb +8 -0
  30. data/lib/gruff/renderer/bezier.rb +1 -0
  31. data/lib/gruff/renderer/circle.rb +1 -0
  32. data/lib/gruff/renderer/dash_line.rb +1 -0
  33. data/lib/gruff/renderer/dot.rb +13 -0
  34. data/lib/gruff/renderer/ellipse.rb +1 -0
  35. data/lib/gruff/renderer/line.rb +7 -0
  36. data/lib/gruff/renderer/polygon.rb +1 -0
  37. data/lib/gruff/renderer/polyline.rb +1 -0
  38. data/lib/gruff/renderer/rectangle.rb +15 -5
  39. data/lib/gruff/renderer/renderer.rb +26 -3
  40. data/lib/gruff/renderer/text.rb +5 -1
  41. data/lib/gruff/scatter.rb +17 -0
  42. data/lib/gruff/side_bar.rb +9 -5
  43. data/lib/gruff/side_stacked_bar.rb +3 -0
  44. data/lib/gruff/spider.rb +26 -2
  45. data/lib/gruff/stacked_area.rb +5 -0
  46. data/lib/gruff/stacked_bar.rb +5 -5
  47. data/lib/gruff/store/basic_data.rb +4 -0
  48. data/lib/gruff/store/store.rb +8 -0
  49. data/lib/gruff/store/xy_data.rb +2 -0
  50. data/lib/gruff/store/xy_pointsizes_data.rb +2 -0
  51. data/lib/gruff/version.rb +1 -1
  52. data/lib/gruff.rb +2 -0
  53. data/sig/generated/gruff/accumulator_bar.rbs +2 -1
  54. data/sig/generated/gruff/area.rbs +4 -2
  55. data/sig/generated/gruff/bar.rbs +10 -8
  56. data/sig/generated/gruff/base.rbs +129 -64
  57. data/sig/generated/gruff/bezier.rbs +2 -1
  58. data/sig/generated/gruff/box.rbs +13 -5
  59. data/sig/generated/gruff/bubble.rbs +8 -4
  60. data/sig/generated/gruff/bullet.rbs +8 -4
  61. data/sig/generated/gruff/candlestick.rbs +24 -12
  62. data/sig/generated/gruff/dot.rbs +8 -7
  63. data/sig/generated/gruff/font.rbs +3 -1
  64. data/sig/generated/gruff/helper/bar_value_label.rbs +4 -2
  65. data/sig/generated/gruff/helper/stacked_mixin.rbs +2 -1
  66. data/sig/generated/gruff/histogram.rbs +6 -3
  67. data/sig/generated/gruff/line.rbs +44 -16
  68. data/sig/generated/gruff/mini/bar.rbs +6 -3
  69. data/sig/generated/gruff/mini/legend.rbs +20 -10
  70. data/sig/generated/gruff/mini/pie.rbs +6 -3
  71. data/sig/generated/gruff/mini/side_bar.rbs +6 -3
  72. data/sig/generated/gruff/net.rbs +12 -6
  73. data/sig/generated/gruff/patch/rmagick.rbs +12 -2
  74. data/sig/generated/gruff/patch/string.rbs +3 -1
  75. data/sig/generated/gruff/pie.rbs +15 -7
  76. data/sig/generated/gruff/renderer/bezier.rbs +2 -1
  77. data/sig/generated/gruff/renderer/circle.rbs +2 -1
  78. data/sig/generated/gruff/renderer/dash_line.rbs +2 -1
  79. data/sig/generated/gruff/renderer/dot.rbs +17 -4
  80. data/sig/generated/gruff/renderer/ellipse.rbs +2 -1
  81. data/sig/generated/gruff/renderer/line.rbs +9 -2
  82. data/sig/generated/gruff/renderer/polygon.rbs +2 -1
  83. data/sig/generated/gruff/renderer/polyline.rbs +2 -1
  84. data/sig/generated/gruff/renderer/rectangle.rbs +4 -2
  85. data/sig/generated/gruff/renderer/renderer.rbs +31 -8
  86. data/sig/generated/gruff/renderer/text.rbs +7 -3
  87. data/sig/generated/gruff/scatter.rbs +30 -13
  88. data/sig/generated/gruff/side_bar.rbs +15 -9
  89. data/sig/generated/gruff/side_stacked_bar.rbs +6 -3
  90. data/sig/generated/gruff/spider.rbs +35 -11
  91. data/sig/generated/gruff/stacked_area.rbs +9 -4
  92. data/sig/generated/gruff/stacked_bar.rbs +10 -8
  93. data/sig/generated/gruff/store/basic_data.rbs +8 -4
  94. data/sig/generated/gruff/store/store.rbs +12 -4
  95. data/sig/generated/gruff/store/xy_data.rbs +4 -2
  96. data/sig/generated/gruff/store/xy_pointsizes_data.rbs +4 -2
  97. data/sig/generated/gruff.rbs +3 -1
  98. metadata +3 -2
data/lib/gruff/base.rb CHANGED
@@ -23,7 +23,7 @@ module Gruff
23
23
  # A common base class inherited from class of drawing a graph.
24
24
  class Base
25
25
  # Space around text elements. Mostly used for vertical spacing.
26
- LEGEND_MARGIN = 20.0
26
+ LEGEND_MARGIN = 10.0
27
27
  TITLE_MARGIN = 20.0
28
28
  LABEL_MARGIN = 15.0
29
29
  DEFAULT_MARGIN = 20.0
@@ -48,9 +48,6 @@ module Gruff
48
48
  # Blank space below the title. Default is +20+.
49
49
  attr_writer :title_margin #: Float | Integer
50
50
 
51
- # Blank space below the legend. Default is +20+.
52
- attr_writer :legend_margin #: Float | Integer
53
-
54
51
  # Truncates labels if longer than max specified.
55
52
  attr_writer :label_max_size #: Float | Integer
56
53
 
@@ -115,13 +112,16 @@ module Gruff
115
112
  # first. This does not affect the legend. Default is +false+.
116
113
  attr_writer :sorted_drawing #: bool
117
114
 
118
- # Display the legend under the graph. Default is +false+.
119
- attr_writer :legend_at_bottom #: bool
115
+ # Blank space below the legend. Default is +20+.
116
+ attr_writer :legend_margin #: Float | Integer
120
117
 
121
- # Optionally set the size of the colored box by each item in the legend.
122
- # Default is +20.0+.
123
- #
124
- # Will be scaled down if graph is smaller than 800px wide.
118
+ # Set the vertical spacing between individual legend items. Default is +5.0+.
119
+ attr_writer :legend_spacing #: Float | Integer
120
+
121
+ # Set the inner padding between the legend frame and its contents. Default is +7.0+.
122
+ attr_writer :legend_padding #: Float | Integer
123
+
124
+ # Optionally set the size of the colored box by each item in the legend. Default is +20.0+.
125
125
  attr_writer :legend_box_size #: Float | Integer
126
126
 
127
127
  # If one numerical argument is given, the graph is drawn at 4/3 ratio
@@ -154,6 +154,7 @@ module Gruff
154
154
  self.theme = Themes::KEYNOTE
155
155
  end
156
156
 
157
+ # @rbs return: void
157
158
  def initialize_graph_scale
158
159
  @raw_columns = DEFAULT_TARGET_WIDTH
159
160
  @raw_rows = DEFAULT_TARGET_WIDTH * (@rows / @columns)
@@ -165,6 +166,7 @@ module Gruff
165
166
  end
166
167
  protected :initialize_graph_scale
167
168
 
169
+ # @rbs return: void
168
170
  def initialize_store
169
171
  @store = Gruff::Store.new(Gruff::Store::BasicData)
170
172
  end
@@ -176,6 +178,8 @@ module Gruff
176
178
  #
177
179
  # This makes it possible to set defaults in a subclass but still allow
178
180
  # developers to change this values in their program.
181
+ #
182
+ # @rbs return: void
179
183
  def initialize_attributes
180
184
  @marker_count = nil
181
185
  @maximum_value = @minimum_value = nil
@@ -186,19 +190,22 @@ module Gruff
186
190
 
187
191
  @title_font = Gruff::Font.new(size: 36.0, bold: true)
188
192
  @marker_font = Gruff::Font.new(size: 21.0)
189
- @legend_font = Gruff::Font.new(size: 20.0)
193
+ @legend_font = Gruff::Font.new(size: 12.0)
190
194
  @no_data_font = Gruff::Font.new(size: 80.0)
191
195
 
192
196
  @label_margin = LABEL_MARGIN
193
197
  @top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
194
- @legend_margin = LEGEND_MARGIN
195
198
  @title_margin = TITLE_MARGIN
196
199
 
197
- @legend_box_size = 20.0
200
+ @legend_margin = LEGEND_MARGIN
201
+ @legend_spacing = 5.0
202
+ @legend_padding = 7.0
203
+ @legend_box_size = 10.0
204
+ @legend_position = :top_right
198
205
 
199
206
  @no_data_message = 'No Data'
200
207
 
201
- @hide_line_markers = @hide_legend = @hide_title = @hide_line_numbers = @legend_at_bottom = false
208
+ @hide_line_markers = @hide_legend = @hide_title = @hide_line_numbers = false
202
209
  @label_max_size = 0
203
210
  @label_truncation_style = :absolute
204
211
  @label_rotation = 0
@@ -228,6 +235,7 @@ module Gruff
228
235
  # g = Gruff::Bar.new
229
236
  # g.labels = ['2005', nil, nil, '2006', nil, nil, '2007', nil, nil, '2008'] # same labels for columns
230
237
  #
238
+ # @rbs return: void
231
239
  def labels=(labels)
232
240
  if labels.is_a?(Array)
233
241
  labels = labels.each_with_index.with_object({}) do |(label, index), hash|
@@ -243,18 +251,41 @@ module Gruff
243
251
  #
244
252
  # @param rotation [Numeric] the rotation.
245
253
  # @rbs rotation: Float | Integer
254
+ # @rbs return: void
246
255
  def label_rotation=(rotation)
247
256
  raise ArgumentError, 'rotation must be between 0.0 and 45.0 or between 0.0 and -45.0' if rotation > 45.0 || rotation < -45.0
248
257
 
249
258
  @label_rotation = rotation.to_f
250
259
  end
251
260
 
261
+ # Set the corner position of the floating legend. Accepts +:top_right+ (default),
262
+ # +:top_left+, +:bottom_right+, or +:bottom_left+.
263
+ #
264
+ # @param position [Symbol] the position.
265
+ # @rbs position: Symbol
266
+ # @rbs return: void
267
+ def legend_position=(position)
268
+ unless %i[top_right top_left bottom_right bottom_left].include?(position)
269
+ raise ArgumentError, 'Invalid legend position. Must be :top_right, :top_left, :bottom_right, or :bottom_left.'
270
+ end
271
+
272
+ @legend_position = position
273
+ end
274
+
252
275
  # Height of staggering between labels.
253
276
  # @deprecated
277
+ # @rbs return: void
254
278
  def label_stagger_height=(_value)
255
279
  warn '#label_stagger_height= is deprecated. It is no longer effective.'
256
280
  end
257
281
 
282
+ # Set the legend position to the bottom of the graph.
283
+ # @deprecated
284
+ # @rbs return: void
285
+ def legend_at_bottom=(_value)
286
+ warn '#legend_at_bottom= is deprecated. It is no longer effective.'
287
+ end
288
+
258
289
  # Set the large title of the graph displayed at the top.
259
290
  # You can draw a multi-line title by putting a line break in the string
260
291
  # or by setting an array as argument.
@@ -269,6 +300,7 @@ module Gruff
269
300
  # g = Gruff::Bar.new
270
301
  # g.title = ['The first line of title', 'The second line of title']
271
302
  #
303
+ # @rbs return: void
272
304
  def title=(title)
273
305
  if title.is_a?(Array)
274
306
  title = title.join("\n")
@@ -281,6 +313,7 @@ module Gruff
281
313
  #
282
314
  # @param margin [Numeric] The margin size.
283
315
  # @rbs margin: Float | Integer
316
+ # @rbs return: void
284
317
  def margins=(margin)
285
318
  @top_margin = @left_margin = @right_margin = @bottom_margin = margin
286
319
  end
@@ -289,6 +322,7 @@ module Gruff
289
322
  #
290
323
  # @param font_path [String] The path to font.
291
324
  # @rbs font_path: String
325
+ # @rbs return: void
292
326
  def font=(font_path)
293
327
  @title_font.path = font_path unless @title_font.path
294
328
  @marker_font.path = font_path
@@ -300,6 +334,7 @@ module Gruff
300
334
  #
301
335
  # @param font_path [String] The path to font.
302
336
  # @rbs font_path: String
337
+ # @rbs return: void
303
338
  def title_font=(font_path)
304
339
  @title_font.path = font_path
305
340
  end
@@ -308,6 +343,7 @@ module Gruff
308
343
  #
309
344
  # @param value [Numeric] title font size
310
345
  # @rbs value: Float | Integer
346
+ # @rbs return: void
311
347
  def title_font_size=(value)
312
348
  @title_font.size = value
313
349
  end
@@ -316,6 +352,7 @@ module Gruff
316
352
  #
317
353
  # @param value [Numeric] marker font size
318
354
  # @rbs value: Float | Integer
355
+ # @rbs return: void
319
356
  def marker_font_size=(value)
320
357
  @marker_font.size = value
321
358
  end
@@ -327,6 +364,7 @@ module Gruff
327
364
  #
328
365
  # @param value [Numeric] legend font size
329
366
  # @rbs value: Float | Integer
367
+ # @rbs return: void
330
368
  def legend_font_size=(value)
331
369
  @legend_font.size = value
332
370
  end
@@ -335,6 +373,7 @@ module Gruff
335
373
  #
336
374
  # @param value [Numeric] no data font size
337
375
  # @rbs value: Float | Integer
376
+ # @rbs return: void
338
377
  def no_data_font_size=(value)
339
378
  @no_data_font.size = value
340
379
  end
@@ -343,6 +382,7 @@ module Gruff
343
382
  #
344
383
  # @param value [Boolean] specifies whether to draw the title bolded or not.
345
384
  # @rbs value: bool
385
+ # @rbs return: void
346
386
  def bold_title=(value)
347
387
  @title_font.bold = value
348
388
  end
@@ -351,6 +391,7 @@ module Gruff
351
391
  #
352
392
  # @param value [String] color
353
393
  # @rbs value: String
394
+ # @rbs return: void
354
395
  def font_color=(value)
355
396
  @title_font.color = value
356
397
  @marker_font.color = value
@@ -365,6 +406,7 @@ module Gruff
365
406
  #
366
407
  # @example
367
408
  # add_color('#c0e9d3')
409
+ # @rbs return: void
368
410
  def add_color(colorname)
369
411
  @colors << colorname
370
412
  end
@@ -385,6 +427,7 @@ module Gruff
385
427
  #
386
428
  # @example
387
429
  # replace_colors ['#cc99cc', '#d9e043', '#34d8a2']
430
+ # @rbs return: void
388
431
  def replace_colors(color_list = [])
389
432
  @colors = color_list
390
433
  end
@@ -393,6 +436,7 @@ module Gruff
393
436
  #
394
437
  # @param value [Boolean] Specify whether to make background transparent.
395
438
  # @rbs value: bool
439
+ # @rbs return: void
396
440
  def transparent_background=(value)
397
441
  @renderer.transparent_background(@columns, @rows) if value
398
442
  end
@@ -428,6 +472,7 @@ module Gruff
428
472
  #
429
473
  # @param options [Hash] The optional setting for theme
430
474
  # @rbs options: Hash[Symbol, untyped]
475
+ # @rbs return: void
431
476
  def theme=(options)
432
477
  reset_themes
433
478
 
@@ -451,31 +496,37 @@ module Gruff
451
496
  end
452
497
 
453
498
  # Apply Apple's keynote theme.
499
+ # @rbs return: void
454
500
  def theme_keynote
455
501
  self.theme = Themes::KEYNOTE
456
502
  end
457
503
 
458
504
  # Apply 37signals theme.
505
+ # @rbs return: void
459
506
  def theme_37signals
460
507
  self.theme = Themes::THIRTYSEVEN_SIGNALS
461
508
  end
462
509
 
463
510
  # Apply Rails theme.
511
+ # @rbs return: void
464
512
  def theme_rails_keynote
465
513
  self.theme = Themes::RAILS_KEYNOTE
466
514
  end
467
515
 
468
516
  # Apply Odeo theme.
517
+ # @rbs return: void
469
518
  def theme_odeo
470
519
  self.theme = Themes::ODEO
471
520
  end
472
521
 
473
522
  # Apply pastel theme.
523
+ # @rbs return: void
474
524
  def theme_pastel
475
525
  self.theme = Themes::PASTEL
476
526
  end
477
527
 
478
528
  # Apply greyscale theme.
529
+ # @rbs return: void
479
530
  def theme_greyscale
480
531
  self.theme = Themes::GREYSCALE
481
532
  end
@@ -503,6 +554,7 @@ module Gruff
503
554
  #
504
555
  # @example
505
556
  # data("Bart S.", [95, 45, 78, 89, 88, 76], '#ffcc00')
557
+ # @rbs return: void
506
558
  def data(name, data_points = [], color = nil)
507
559
  store.add(name, data_points, color)
508
560
  end
@@ -540,6 +592,7 @@ module Gruff
540
592
  #
541
593
  # @example
542
594
  # write('graphs/my_pretty_graph.png')
595
+ # @rbs return: void
543
596
  def write(file_name = 'graph.png')
544
597
  to_image.write(file_name)
545
598
  end
@@ -561,6 +614,7 @@ module Gruff
561
614
  # image = image.resize(400, 300).quantize(128, Magick::RGBColorspace)
562
615
  # image.write('test.png')
563
616
  #
617
+ # @rbs return: untyped
564
618
  def to_image(format = 'PNG')
565
619
  @to_image ||= begin
566
620
  draw
@@ -587,6 +641,7 @@ module Gruff
587
641
  end
588
642
 
589
643
  # Draw a graph.
644
+ # @rbs return: void
590
645
  def draw
591
646
  setup_data
592
647
 
@@ -598,11 +653,11 @@ module Gruff
598
653
 
599
654
  setup_drawing
600
655
 
601
- draw_legend
602
656
  draw_line_markers
603
657
  draw_axis_labels
604
658
  draw_title
605
659
  draw_graph
660
+ draw_legend
606
661
  end
607
662
 
608
663
  protected
@@ -610,6 +665,7 @@ module Gruff
610
665
  attr_reader :renderer #: Gruff::Renderer
611
666
 
612
667
  # Perform data manipulation before calculating chart measurements
668
+ # @rbs return: void
613
669
  def setup_data
614
670
  if @y_axis_increment && !@hide_line_markers
615
671
  self.maximum_value = [@y_axis_increment, maximum_value, (maximum_value / @y_axis_increment).round * @y_axis_increment].max
@@ -624,6 +680,7 @@ module Gruff
624
680
  # * line markers
625
681
  # * legend
626
682
  # * title
683
+ # @rbs return: void
627
684
  def setup_drawing
628
685
  calculate_spread
629
686
  calculate_increment
@@ -666,10 +723,12 @@ module Gruff
666
723
 
667
724
  # Make copy of data with values scaled between 0-100
668
725
  # @rbs return: Array[Gruff::Store::BasicData | Gruff::Store::XYData | Gruff::Store::XYPointsizeData]
726
+ # @rbs return: void
669
727
  def normalize
670
728
  store.normalize(minimum: minimum_value, spread: @spread)
671
729
  end
672
730
 
731
+ # @rbs return: Float
673
732
  def calculate_spread
674
733
  @spread = maximum_value.to_f - minimum_value.to_f
675
734
  @spread = @spread > 0 ? @spread : 1.0
@@ -698,6 +757,7 @@ module Gruff
698
757
  ##
699
758
  # Calculates size of drawable area, general font dimensions, etc.
700
759
 
760
+ # @rbs return: void
701
761
  def setup_graph_measurements
702
762
  @graph_right = setup_right_margin
703
763
  @graph_left = setup_left_margin
@@ -709,6 +769,7 @@ module Gruff
709
769
  end
710
770
 
711
771
  # Draw the optional labels for the x axis and y axis.
772
+ # @rbs return: void
712
773
  def draw_axis_labels
713
774
  if @x_axis_label
714
775
  # X Axis
@@ -728,6 +789,7 @@ module Gruff
728
789
  end
729
790
 
730
791
  # Draws horizontal background lines and labels
792
+ # @rbs return: void
731
793
  def draw_line_markers
732
794
  return if @hide_line_markers
733
795
 
@@ -747,11 +809,16 @@ module Gruff
747
809
  end
748
810
  end
749
811
 
812
+ # @rbs y: Float | Integer
813
+ # @rbs return: void
750
814
  def draw_marker_horizontal_line(y)
751
815
  Gruff::Renderer::Line.new(renderer, color: @marker_color).render(@graph_left, y, @graph_right, y)
752
816
  Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(@graph_left, y + 1, @graph_right, y + 1) if @marker_shadow_color
753
817
  end
754
818
 
819
+ # @rbs x: Float | Integer
820
+ # @rbs tick_mark_mode: bool
821
+ # @rbs return: void
755
822
  def draw_marker_vertical_line(x, tick_mark_mode: false)
756
823
  if tick_mark_mode
757
824
  Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_bottom + 5)
@@ -775,55 +842,68 @@ module Gruff
775
842
 
776
843
  # Draws a legend with the names of the datasets matched
777
844
  # to the colors used to draw them.
845
+ # @rbs return: void
778
846
  def draw_legend
779
847
  return if @hide_legend
780
848
 
781
- legend_labels = store.data.map(&:label)
782
- legend_square_width = @legend_box_size # small square with color of this item
783
- legend_label_lines = calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
784
- line_height = [legend_caps_height, legend_square_width].max + @legend_margin
785
-
786
- current_y_offset = begin
787
- if @legend_at_bottom
788
- @graph_bottom + @legend_margin + labels_caps_height + @label_margin + (@x_axis_label ? (@label_margin * 2) + marker_caps_height : 0)
789
- else
790
- hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + title_caps_height
791
- end
849
+ legend_labels = store.data.map(&:label).reject(&:empty?)
850
+ return if legend_labels.empty?
851
+
852
+ line_height = [legend_caps_height, @legend_box_size].max + @legend_spacing
853
+ max_legend_label_width = legend_labels.map { |l| calculate_width(@legend_font, l) }.max || 0.0
854
+
855
+ legend_content_width = (@legend_box_size * 1.5) + max_legend_label_width
856
+ legend_content_height = (line_height * (legend_labels.size - 1)) + @legend_box_size
857
+
858
+ case @legend_position
859
+ when :top_left
860
+ current_x_offset = @graph_left + @legend_margin
861
+ current_y_offset = @graph_top + @legend_margin + @legend_spacing
862
+ when :bottom_right
863
+ current_x_offset = @graph_right - @legend_margin - legend_content_width
864
+ current_y_offset = @graph_bottom - @legend_margin - legend_content_height
865
+ when :bottom_left
866
+ current_x_offset = @graph_left + @legend_margin
867
+ current_y_offset = @graph_bottom - @legend_margin - legend_content_height
868
+ else # :top_right (default)
869
+ current_x_offset = @graph_right - @legend_margin - legend_content_width
870
+ current_y_offset = @graph_top + @legend_margin + @legend_spacing
792
871
  end
793
872
 
794
- index = 0
795
- legend_label_lines.each do |(legend_labels_width, legend_labels_line)|
796
- current_x_offset = center(legend_labels_width)
797
-
798
- legend_labels_line.each do |legend_label|
799
- unless legend_label.empty?
800
- legend_label_width = calculate_width(@legend_font, legend_label)
801
-
802
- # Draw label
803
- text_renderer = Gruff::Renderer::Text.new(renderer, legend_label, font: @legend_font)
804
- text_renderer.add_to_render_queue(legend_label_width,
805
- legend_square_width,
806
- current_x_offset + (legend_square_width * 1.7),
807
- current_y_offset,
808
- Magick::CenterGravity)
809
-
810
- # Now draw box with color of this dataset
811
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
812
- rect_renderer.render(current_x_offset,
813
- current_y_offset,
814
- current_x_offset + legend_square_width,
815
- current_y_offset + legend_square_width)
816
-
817
- current_x_offset += legend_label_width + (legend_square_width * 2.7)
818
- end
819
- index += 1
820
- end
873
+ legend_items_end_x = current_x_offset + legend_content_width
874
+ legend_items_end_y = current_y_offset + legend_content_height
875
+
876
+ frame_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @marker_color, width: 1.1, opacity: 0.2, round: true)
877
+ frame_renderer.render(current_x_offset - @legend_padding,
878
+ current_y_offset - @legend_padding,
879
+ legend_items_end_x + @legend_padding,
880
+ legend_items_end_y + @legend_padding)
881
+
882
+ store.data.each do |data_row|
883
+ legend_label = data_row.label
884
+ next if legend_label.empty?
885
+
886
+ legend_label_width = calculate_width(@legend_font, legend_label)
887
+
888
+ text_renderer = Gruff::Renderer::Text.new(renderer, legend_label, font: @legend_font)
889
+ text_renderer.add_to_render_queue(legend_label_width,
890
+ @legend_box_size,
891
+ current_x_offset + (@legend_box_size * 1.5),
892
+ current_y_offset,
893
+ Magick::CenterGravity)
894
+
895
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
896
+ rect_renderer.render(current_x_offset,
897
+ current_y_offset,
898
+ current_x_offset + @legend_box_size,
899
+ current_y_offset + @legend_box_size)
821
900
 
822
901
  current_y_offset += line_height
823
902
  end
824
903
  end
825
904
 
826
905
  # Draws a title on the graph.
906
+ # @rbs return: void
827
907
  def draw_title
828
908
  return if hide_title?
829
909
 
@@ -842,6 +922,7 @@ module Gruff
842
922
  # @rbs index: Integer
843
923
  # @rbs gravity: untyped
844
924
  # @rbs &: () -> void
925
+ # @rbs return: void
845
926
  def draw_label(x, index, gravity = Magick::NorthGravity, &block)
846
927
  draw_unique_label(index) do
847
928
  if x.between?(@graph_left, @graph_right)
@@ -856,6 +937,7 @@ module Gruff
856
937
 
857
938
  # @rbs index: Integer
858
939
  # @rbs yields: () -> void
940
+ # @rbs return: void
859
941
  def draw_unique_label(index)
860
942
  return if hide_labels?
861
943
 
@@ -873,6 +955,7 @@ module Gruff
873
955
  # @rbs text: String | _ToS
874
956
  # @rbs gravity: untyped
875
957
  # @rbs rotation: Float | Integer
958
+ # @rbs return: void
876
959
  def draw_label_at(width, height, x, y, text, gravity: Magick::NorthGravity, rotation: 0)
877
960
  label_text = truncate_label_text(text)
878
961
  text_renderer = Gruff::Renderer::Text.new(renderer, label_text, font: @marker_font, rotation: rotation)
@@ -887,6 +970,7 @@ module Gruff
887
970
  # @rbs y_offset: Float | Integer
888
971
  # @rbs data_point: String | _ToS
889
972
  # @rbs gravity: untyped
973
+ # @rbs return: void
890
974
  def draw_value_label(width, height, x_offset, y_offset, data_point, gravity: Magick::CenterGravity)
891
975
  return if @hide_line_markers
892
976
 
@@ -894,17 +978,20 @@ module Gruff
894
978
  end
895
979
 
896
980
  # Shows an error message because you have no data.
981
+ # @rbs return: void
897
982
  def draw_no_data
898
983
  font = @no_data_font
899
984
  text_renderer = Gruff::Renderer::Text.new(renderer, @no_data_message, font: font)
900
985
  text_renderer.render(@raw_columns, @raw_rows, 0, 0, Magick::CenterGravity)
901
986
  end
902
987
 
988
+ # @rbs return: void
903
989
  def draw_graph
904
990
  raise 'Should implement this method at inherited class.'
905
991
  end
906
992
 
907
993
  # Resets everything to defaults (except data).
994
+ # @rbs return: void
908
995
  def reset_themes
909
996
  @theme_options = {}
910
997
  end
@@ -945,17 +1032,20 @@ module Gruff
945
1032
  end
946
1033
 
947
1034
  # Sort with largest overall summed value at front of array.
1035
+ # @rbs return: void
948
1036
  def sort_data
949
1037
  store.sort_data!
950
1038
  end
951
1039
 
952
1040
  # Set the color for each data set unless it was given in the data(...) call.
1041
+ # @rbs return: void
953
1042
  def set_colors
954
1043
  store.change_colors(@colors)
955
1044
  end
956
1045
 
957
1046
  # Sort with largest overall summed value at front of array so it shows up
958
1047
  # correctly in the drawn graph.
1048
+ # @rbs return: void
959
1049
  def sort_norm_data
960
1050
  store.sort_norm_data!
961
1051
  end
@@ -1068,14 +1158,12 @@ module Gruff
1068
1158
  # When @hide title, leave a title_margin space for aesthetics.
1069
1159
  # Same with @hide_legend
1070
1160
  @top_margin +
1071
- (hide_title? ? @title_margin : title_caps_height + @title_margin) +
1072
- (@hide_legend || @legend_at_bottom ? @legend_margin : calculate_legend_height + @legend_margin)
1161
+ (hide_title? ? @title_margin : title_caps_height + @title_margin)
1073
1162
  end
1074
1163
 
1075
1164
  # @rbs return: Float
1076
1165
  def setup_bottom_margin
1077
1166
  graph_bottom_margin = hide_bottom_label_area? ? @bottom_margin : @bottom_margin + labels_caps_height + @label_margin
1078
- graph_bottom_margin += (calculate_legend_height + @legend_margin) if @legend_at_bottom
1079
1167
 
1080
1168
  x_axis_label_height = @x_axis_label.nil? ? 0.0 : marker_caps_height + (@label_margin * 2)
1081
1169
  @raw_rows - graph_bottom_margin - x_axis_label_height
@@ -1156,40 +1244,6 @@ module Gruff
1156
1244
  end
1157
1245
  end
1158
1246
 
1159
- # TODO: RBS signature
1160
- def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
1161
- label_widths = [[]]
1162
- label_lines = [[]]
1163
- legend_labels.each do |label|
1164
- if label.empty?
1165
- label_width = 0.0
1166
- else
1167
- width = calculate_width(@legend_font, label)
1168
- label_width = width + (legend_square_width * 2.7)
1169
- end
1170
- label_widths.last.push label_width
1171
- label_lines.last.push label
1172
-
1173
- if label_widths.last.sum > (@raw_columns * 0.9)
1174
- label_widths.push [label_widths.last.pop]
1175
- label_lines.push [label_lines.last.pop]
1176
- end
1177
- end
1178
-
1179
- label_widths.map(&:sum).zip(label_lines)
1180
- end
1181
-
1182
- # TODO: RBS signature
1183
- def calculate_legend_height
1184
- return 0.0 if @hide_legend
1185
-
1186
- legend_labels = store.data.map(&:label)
1187
- legend_label_lines = calculate_legend_label_widths_for_each_line(legend_labels, @legend_box_size)
1188
- line_height = [legend_caps_height, @legend_box_size].max
1189
-
1190
- (line_height * legend_label_lines.count) + (@legend_margin * (legend_label_lines.count - 1))
1191
- end
1192
-
1193
1247
  # Returns the height of the capital letter 'X' for the current font and
1194
1248
  # size.
1195
1249
  #
data/lib/gruff/bezier.rb CHANGED
@@ -23,6 +23,7 @@
23
23
  class Gruff::Bezier < Gruff::Base
24
24
  private
25
25
 
26
+ # @rbs return: void
26
27
  def draw_graph
27
28
  x_increment = (@graph_width / (column_count - 1)).to_f
28
29
 
data/lib/gruff/box.rb CHANGED
@@ -26,6 +26,7 @@ class Gruff::Box < Gruff::Base
26
26
  # Default value is +0.8+.
27
27
  #
28
28
  # @rbs space_percent: Float | Integer
29
+ # @rbs return: void
29
30
  def spacing_factor=(space_percent)
30
31
  raise ArgumentError, 'spacing_factor must be between 0.00 and 1.00' if (space_percent < 0) || (space_percent > 1)
31
32
 
@@ -34,6 +35,7 @@ class Gruff::Box < Gruff::Base
34
35
 
35
36
  private
36
37
 
38
+ # @rbs return: void
37
39
  def initialize_attributes
38
40
  super
39
41
  @fill_opacity = 0.2
@@ -41,6 +43,7 @@ private
41
43
  @spacing_factor = 0.8
42
44
  end
43
45
 
46
+ # @rbs return: void
44
47
  def draw_graph
45
48
  # Setup the BarConversion Object
46
49
  conversion = Gruff::BarConversion.new(
@@ -93,6 +96,7 @@ private
93
96
  end
94
97
  end
95
98
 
99
+ # @rbs return: Array[Gruff::Box::BoxData]
96
100
  def normalized_boxes
97
101
  @normalized_boxes ||= store.norm_data.map { |data| Gruff::Box::BoxData.new(data.label, data.points, data.color) }
98
102
  end
@@ -113,6 +117,10 @@ private
113
117
  attr_accessor :points #: Array[Float | Integer]
114
118
  attr_accessor :color #: String
115
119
 
120
+ # @rbs label: String
121
+ # @rbs points: Array[Float | Integer]
122
+ # @rbs color: String
123
+ # @rbs return: void
116
124
  def initialize(label, points, color)
117
125
  @label = label
118
126
  @points = points.compact.sort