gruff 0.25.0 → 0.27.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.
- checksums.yaml +4 -4
- data/.editorconfig +2 -2
- data/.github/ISSUE_TEMPLATE/report.yml +41 -0
- data/.github/workflows/ci.yml +62 -9
- data/.rubocop.yml +5 -1
- data/CHANGELOG.md +22 -1
- data/Gemfile +8 -3
- data/README.md +9 -3
- data/gruff.gemspec +1 -1
- data/lib/gruff/accumulator_bar.rb +3 -1
- data/lib/gruff/area.rb +5 -2
- data/lib/gruff/bar.rb +18 -9
- data/lib/gruff/base.rb +205 -71
- data/lib/gruff/bezier.rb +6 -3
- data/lib/gruff/box.rb +40 -16
- data/lib/gruff/bubble.rb +9 -2
- data/lib/gruff/bullet.rb +8 -1
- data/lib/gruff/candlestick.rb +30 -8
- data/lib/gruff/dot.rb +13 -3
- data/lib/gruff/font.rb +12 -4
- data/lib/gruff/helper/bar_conversion.rb +12 -1
- data/lib/gruff/helper/bar_mixin.rb +19 -1
- data/lib/gruff/helper/bar_value_label.rb +22 -4
- data/lib/gruff/helper/stacked_mixin.rb +21 -1
- data/lib/gruff/histogram.rb +14 -5
- data/lib/gruff/line.rb +31 -12
- data/lib/gruff/mini/bar.rb +2 -2
- data/lib/gruff/mini/legend.rb +10 -1
- data/lib/gruff/mini/pie.rb +2 -2
- data/lib/gruff/mini/side_bar.rb +2 -2
- data/lib/gruff/net.rb +12 -7
- data/lib/gruff/patch/rmagick.rb +2 -0
- data/lib/gruff/patch/string.rb +1 -1
- data/lib/gruff/pie.rb +46 -11
- data/lib/gruff/renderer/bezier.rb +7 -0
- data/lib/gruff/renderer/circle.rb +11 -0
- data/lib/gruff/renderer/dash_line.rb +11 -0
- data/lib/gruff/renderer/dot.rb +11 -0
- data/lib/gruff/renderer/ellipse.rb +12 -0
- data/lib/gruff/renderer/line.rb +10 -0
- data/lib/gruff/renderer/polygon.rb +6 -0
- data/lib/gruff/renderer/polyline.rb +8 -0
- data/lib/gruff/renderer/rectangle.rb +11 -0
- data/lib/gruff/renderer/renderer.rb +16 -5
- data/lib/gruff/renderer/text.rb +19 -2
- data/lib/gruff/scatter.rb +16 -8
- data/lib/gruff/side_bar.rb +19 -10
- data/lib/gruff/side_stacked_bar.rb +15 -11
- data/lib/gruff/spider.rb +9 -2
- data/lib/gruff/stacked_area.rb +6 -1
- data/lib/gruff/stacked_bar.rb +16 -10
- data/lib/gruff/store/basic_data.rb +36 -2
- data/lib/gruff/store/store.rb +16 -3
- data/lib/gruff/store/xy_data.rb +32 -2
- data/lib/gruff/store/xy_pointsizes_data.rb +36 -3
- data/lib/gruff/themes.rb +2 -0
- data/lib/gruff/version.rb +3 -1
- data/lib/gruff.rb +3 -1
- data/sig/generated/gruff/accumulator_bar.rbs +19 -0
- data/sig/generated/gruff/area.rbs +27 -0
- data/sig/generated/gruff/bar.rbs +74 -0
- data/sig/generated/gruff/base.rbs +672 -0
- data/sig/generated/gruff/bezier.rbs +24 -0
- data/sig/generated/gruff/box.rbs +88 -0
- data/sig/generated/gruff/bubble.rbs +69 -0
- data/sig/generated/gruff/bullet.rbs +30 -0
- data/sig/generated/gruff/candlestick.rbs +79 -0
- data/sig/generated/gruff/dot.rbs +44 -0
- data/sig/generated/gruff/font.rbs +35 -0
- data/sig/generated/gruff/helper/bar_conversion.rbs +27 -0
- data/sig/generated/gruff/helper/bar_mixin.rbs +22 -0
- data/sig/generated/gruff/helper/bar_value_label.rbs +41 -0
- data/sig/generated/gruff/helper/stacked_mixin.rbs +27 -0
- data/sig/generated/gruff/histogram.rbs +42 -0
- data/sig/generated/gruff/line.rbs +165 -0
- data/sig/generated/gruff/net.rbs +52 -0
- data/sig/generated/gruff/pie.rbs +131 -0
- data/sig/generated/gruff/renderer/bezier.rbs +15 -0
- data/sig/generated/gruff/renderer/circle.rbs +19 -0
- data/sig/generated/gruff/renderer/dash_line.rbs +19 -0
- data/sig/generated/gruff/renderer/dot.rbs +27 -0
- data/sig/generated/gruff/renderer/ellipse.rbs +20 -0
- data/sig/generated/gruff/renderer/line.rbs +24 -0
- data/sig/generated/gruff/renderer/polyline.rbs +16 -0
- data/sig/generated/gruff/renderer/rectangle.rbs +19 -0
- data/sig/generated/gruff/renderer/renderer.rbs +43 -0
- data/sig/generated/gruff/renderer/text.rbs +38 -0
- data/sig/generated/gruff/scatter.rbs +112 -0
- data/sig/generated/gruff/side_bar.rbs +78 -0
- data/sig/generated/gruff/side_stacked_bar.rbs +52 -0
- data/sig/generated/gruff/spider.rbs +50 -0
- data/sig/generated/gruff/stacked_area.rbs +25 -0
- data/sig/generated/gruff/stacked_bar.rbs +56 -0
- data/sig/generated/gruff/store/basic_data.rbs +48 -0
- data/sig/generated/gruff/store/store.rbs +53 -0
- data/sig/generated/gruff/store/xy_data.rbs +58 -0
- data/sig/generated/gruff/store/xy_pointsizes_data.rbs +61 -0
- data/sig/generated/gruff/themes.rbs +24 -0
- data/sig/generated/gruff/version.rbs +5 -0
- data/sig/generated/gruff.rbs +20 -0
- metadata +46 -6
@@ -3,6 +3,11 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Polygon
|
6
|
+
# @rbs renderer: Gruff::Renderer
|
7
|
+
# @rbs color: String
|
8
|
+
# @rbs width: Float | Integer
|
9
|
+
# @rbs opacity: Float | Integer
|
10
|
+
# @rbs return: void
|
6
11
|
def initialize(renderer, color:, width: 1.0, opacity: 1.0)
|
7
12
|
@renderer = renderer
|
8
13
|
@color = color
|
@@ -10,6 +15,7 @@ module Gruff
|
|
10
15
|
@opacity = opacity
|
11
16
|
end
|
12
17
|
|
18
|
+
# @rbs points: Array[Float | Integer]
|
13
19
|
def render(points)
|
14
20
|
@renderer.draw.push
|
15
21
|
@renderer.draw.stroke_width(@width)
|
@@ -1,8 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Gruff
|
4
6
|
# @private
|
5
7
|
class Renderer::Polyline
|
8
|
+
# @rbs renderer: Gruff::Renderer
|
9
|
+
# @rbs color: String
|
10
|
+
# @rbs width: Float | Integer
|
11
|
+
# @rbs linejoin: String
|
12
|
+
# @rbs return: void
|
6
13
|
def initialize(renderer, color:, width: 1.0, linejoin: 'bevel')
|
7
14
|
@renderer = renderer
|
8
15
|
@color = color
|
@@ -10,6 +17,7 @@ module Gruff
|
|
10
17
|
@linejoin = linejoin
|
11
18
|
end
|
12
19
|
|
20
|
+
# @rbs points: Array[Float | Integer]
|
13
21
|
def render(points)
|
14
22
|
@renderer.draw.push
|
15
23
|
@renderer.draw.stroke_linejoin(@linejoin)
|
@@ -1,8 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Gruff
|
4
6
|
# @private
|
5
7
|
class Renderer::Rectangle
|
8
|
+
# @rbs renderer: Gruff::Renderer
|
9
|
+
# @rbs color: String
|
10
|
+
# @rbs width: Float | Integer
|
11
|
+
# @rbs opacity: Float | Integer
|
12
|
+
# @rbs return: void
|
6
13
|
def initialize(renderer, color: nil, width: 1.0, opacity: 1.0)
|
7
14
|
@renderer = renderer
|
8
15
|
@color = color
|
@@ -10,6 +17,10 @@ module Gruff
|
|
10
17
|
@opacity = opacity
|
11
18
|
end
|
12
19
|
|
20
|
+
# @rbs upper_left_x: Float | Integer
|
21
|
+
# @rbs upper_left_y: Float | Integer
|
22
|
+
# @rbs lower_right_x: Float | Integer
|
23
|
+
# @rbs lower_right_y: Float | Integer
|
13
24
|
def render(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
14
25
|
@renderer.draw.push
|
15
26
|
@renderer.draw.stroke_width(@width)
|
@@ -1,11 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Gruff
|
4
6
|
# @private
|
5
7
|
class Renderer
|
6
|
-
attr_accessor :text_renderers
|
7
|
-
attr_reader :draw
|
8
|
-
|
8
|
+
attr_accessor :text_renderers #: Array[Gruff::Renderer::Text]
|
9
|
+
attr_reader :draw
|
10
|
+
attr_reader :image
|
11
|
+
attr_reader :scale #: real
|
12
|
+
|
13
|
+
# @rbs columns: Integer
|
14
|
+
# @rbs rows: Integer
|
15
|
+
# @rbs scale: Float | Integer
|
16
|
+
# @rbs theme_options: ::Hash[Symbol, untyped]
|
17
|
+
# @rbs return: void
|
9
18
|
def initialize(columns, rows, scale, theme_options)
|
10
19
|
@draw = Magick::Draw.new
|
11
20
|
@text_renderers = []
|
@@ -23,6 +32,8 @@ module Gruff
|
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
35
|
+
# @rbs columns: Integer
|
36
|
+
# @rbs rows: Integer
|
26
37
|
def transparent_background(columns, rows)
|
27
38
|
@image = render_transparent_background(columns, rows)
|
28
39
|
end
|
@@ -30,11 +41,11 @@ module Gruff
|
|
30
41
|
private
|
31
42
|
|
32
43
|
def background(columns, rows, scale, theme_options)
|
33
|
-
return image_background(scale, *theme_options[:background_image]) if theme_options[:background_image]
|
44
|
+
return image_background(scale, *theme_options[:background_image]) if theme_options[:background_image] # steep:ignore
|
34
45
|
|
35
46
|
case theme_options[:background_colors]
|
36
47
|
when Array
|
37
|
-
gradated_background(columns, rows, *theme_options[:background_colors][0..1], theme_options[:background_direction])
|
48
|
+
gradated_background(columns, rows, *theme_options[:background_colors][0..1], theme_options[:background_direction]) # steep:ignore
|
38
49
|
when String
|
39
50
|
solid_background(columns, rows, theme_options[:background_colors])
|
40
51
|
else
|
data/lib/gruff/renderer/text.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Gruff
|
4
6
|
# @private
|
5
7
|
class Renderer::Text
|
6
8
|
using Magick::GruffAnnotate
|
7
9
|
|
10
|
+
# @rbs renderer: Gruff::Renderer
|
11
|
+
# @rbs text: String
|
12
|
+
# @rbs font: Gruff::Font
|
13
|
+
# @rbs rotation: Float | Integer
|
8
14
|
def initialize(renderer, text, font:, rotation: nil)
|
9
15
|
@renderer = renderer
|
10
16
|
@text = text.to_s
|
@@ -12,8 +18,14 @@ module Gruff
|
|
12
18
|
@rotation = rotation
|
13
19
|
end
|
14
20
|
|
15
|
-
attr_reader :width, :height, :x, :y
|
21
|
+
attr_reader :width, :height, :x, :y #: Float | Integer
|
22
|
+
attr_reader :gravity
|
16
23
|
|
24
|
+
# @rbs width: Float | Integer
|
25
|
+
# @rbs height: Float | Integer
|
26
|
+
# @rbs x: Float | Integer
|
27
|
+
# @rbs y: Float | Integer
|
28
|
+
# @rbs gravity: untyped
|
17
29
|
def add_to_render_queue(width, height, x, y, gravity = Magick::NorthGravity)
|
18
30
|
@width = width
|
19
31
|
@height = height
|
@@ -24,6 +36,11 @@ module Gruff
|
|
24
36
|
@renderer.text_renderers << self
|
25
37
|
end
|
26
38
|
|
39
|
+
# @rbs width: Float | Integer
|
40
|
+
# @rbs height: Float | Integer
|
41
|
+
# @rbs x: Float | Integer
|
42
|
+
# @rbs y: Float | Integer
|
43
|
+
# @rbs gravity: untyped
|
27
44
|
def render(width, height, x, y, gravity = Magick::NorthGravity)
|
28
45
|
@renderer.draw.push
|
29
46
|
@renderer.draw.rotation = @rotation if @rotation
|
@@ -51,7 +68,7 @@ module Gruff
|
|
51
68
|
# This format is used to embed value into a string using image properties.
|
52
69
|
# However, gruff use plain image as canvas which does not have any property.
|
53
70
|
# So, in here, it just escape % in order to avoid SEGV.
|
54
|
-
text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
|
71
|
+
text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s } # steep:ignore
|
55
72
|
|
56
73
|
metrics = @renderer.draw.get_type_metrics(@renderer.image, text)
|
57
74
|
@renderer.draw.pop
|
data/lib/gruff/scatter.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
#
|
4
6
|
# Here's how to set up a Gruff::Scatter.
|
5
7
|
#
|
@@ -11,21 +13,21 @@
|
|
11
13
|
class Gruff::Scatter < Gruff::Base
|
12
14
|
# Maximum X Value. The value will get overwritten by the max in the
|
13
15
|
# datasets.
|
14
|
-
attr_writer :maximum_x_value
|
16
|
+
attr_writer :maximum_x_value #: Float | Integer
|
15
17
|
|
16
18
|
# Minimum X Value. The value will get overwritten by the min in the
|
17
19
|
# datasets.
|
18
|
-
attr_writer :minimum_x_value
|
20
|
+
attr_writer :minimum_x_value #: Float | Integer
|
19
21
|
|
20
22
|
# The number of vertical lines shown for reference.
|
21
|
-
attr_writer :marker_x_count
|
23
|
+
attr_writer :marker_x_count #: Integer
|
22
24
|
|
23
25
|
# Attributes to allow customising the size of the points.
|
24
|
-
attr_writer :circle_radius
|
25
|
-
attr_writer :stroke_width
|
26
|
+
attr_writer :circle_radius #: Float | Integer
|
27
|
+
attr_writer :stroke_width #: Float | Integer
|
26
28
|
|
27
29
|
# Allow for vertical marker lines.
|
28
|
-
attr_writer :show_vertical_markers
|
30
|
+
attr_writer :show_vertical_markers #: bool
|
29
31
|
|
30
32
|
# Allow enabling vertical lines. When you have a lot of data, they can work great.
|
31
33
|
# @deprecated Please use {#show_vertical_markers=} instead.
|
@@ -87,6 +89,10 @@ class Gruff::Scatter < Gruff::Base
|
|
87
89
|
# g.data('oranges', [1,1,1], [2,3,4])
|
88
90
|
# g.data('bitter_melon', [3,5,6], [6,7,8], '#000000')
|
89
91
|
#
|
92
|
+
# @rbs name: String | Symbol
|
93
|
+
# @rbs x_data_points: Array[nil | Float | Integer] | nil
|
94
|
+
# @rbs y_data_points: Array[nil | Float | Integer] | nil
|
95
|
+
# @rbs color: String
|
90
96
|
def data(name, x_data_points = [], y_data_points = [], color = nil)
|
91
97
|
# make sure it's an array
|
92
98
|
x_data_points = Array(x_data_points)
|
@@ -142,8 +148,8 @@ private
|
|
142
148
|
end
|
143
149
|
|
144
150
|
def draw_graph
|
145
|
-
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first
|
146
|
-
circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first
|
151
|
+
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first.x_points.size * 4.0), 5.0)
|
152
|
+
circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.x_points.size * 2.5), 5.0)
|
147
153
|
|
148
154
|
store.norm_data.each do |data_row|
|
149
155
|
data_row.coordinates.each do |x_value, y_value|
|
@@ -195,6 +201,7 @@ private
|
|
195
201
|
end
|
196
202
|
end
|
197
203
|
|
204
|
+
# @rbs return: Integer
|
198
205
|
def marker_x_count
|
199
206
|
# TODO: Do the same for larger numbers...100, 75, 50, 25
|
200
207
|
@marker_x_count ||= begin
|
@@ -212,6 +219,7 @@ private
|
|
212
219
|
end
|
213
220
|
end
|
214
221
|
|
222
|
+
# @rbs return: Float | Integer | BigDecimal
|
215
223
|
def x_increment
|
216
224
|
@x_increment ||= begin
|
217
225
|
if @x_axis_increment.nil?
|
data/lib/gruff/side_bar.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
require_relative 'helper/bar_mixin'
|
4
6
|
|
5
7
|
# Graph with individual horizontal bars instead of vertical bars.
|
@@ -21,30 +23,32 @@ require_relative 'helper/bar_mixin'
|
|
21
23
|
# g.write('sidebar.png')
|
22
24
|
#
|
23
25
|
class Gruff::SideBar < Gruff::Base
|
24
|
-
include BarMixin
|
26
|
+
include Gruff::Base::BarMixin
|
25
27
|
|
26
28
|
# Spacing factor applied between bars.
|
27
|
-
attr_writer :bar_spacing
|
29
|
+
attr_writer :bar_spacing #: Float | Integer
|
28
30
|
|
29
31
|
# Spacing factor applied between a group of bars belonging to the same label.
|
30
|
-
attr_writer :group_spacing
|
32
|
+
attr_writer :group_spacing #: Float | Integer
|
31
33
|
|
32
34
|
# Set the number output format string or lambda.
|
33
35
|
# Default is +"%.2f"+.
|
34
|
-
attr_writer :label_formatting
|
36
|
+
attr_writer :label_formatting #: nil | String | Proc
|
35
37
|
|
36
38
|
# Output the values for the bars on a bar graph.
|
37
39
|
# Default is +false+.
|
38
|
-
attr_writer :show_labels_for_bar_values
|
40
|
+
attr_writer :show_labels_for_bar_values #: bool
|
39
41
|
|
40
42
|
# Prevent drawing of column labels left of a side bar graph. Default is +false+.
|
41
|
-
attr_writer :hide_labels
|
43
|
+
attr_writer :hide_labels #: bool
|
42
44
|
|
43
45
|
# Value to avoid completely overwriting the coordinate axis
|
44
46
|
AXIS_MARGIN = 0.5
|
45
47
|
private_constant :AXIS_MARGIN
|
46
48
|
|
47
|
-
|
49
|
+
# @rbs target_width: (String | Float | Integer)
|
50
|
+
# @rbs return: void
|
51
|
+
def initialize(target_width = DEFAULT_TARGET_WIDTH)
|
48
52
|
super
|
49
53
|
@has_left_labels = true
|
50
54
|
end
|
@@ -66,14 +70,17 @@ private
|
|
66
70
|
@hide_labels = false
|
67
71
|
end
|
68
72
|
|
73
|
+
# @rbs return: bool
|
69
74
|
def hide_labels?
|
70
75
|
@hide_labels
|
71
76
|
end
|
72
77
|
|
78
|
+
# @rbs return: bool
|
73
79
|
def hide_left_label_area?
|
74
80
|
hide_labels? && @y_axis_label.nil?
|
75
81
|
end
|
76
82
|
|
83
|
+
# @rbs return: bool
|
77
84
|
def hide_bottom_label_area?
|
78
85
|
@hide_line_markers && @x_axis_label.nil? && @legend_at_bottom == false
|
79
86
|
end
|
@@ -103,7 +110,7 @@ private
|
|
103
110
|
#
|
104
111
|
bars_width = (@graph_height - calculate_spacing) / column_count
|
105
112
|
bar_width = bars_width / store.length
|
106
|
-
padding = (bar_width * (1 - @bar_spacing)) / 2
|
113
|
+
padding = (bar_width * (1.0 - @bar_spacing)) / 2
|
107
114
|
|
108
115
|
# Setup the BarConversion Object
|
109
116
|
conversion = Gruff::BarConversion.new(
|
@@ -114,12 +121,12 @@ private
|
|
114
121
|
group_left_y = @graph_top
|
115
122
|
|
116
123
|
normalized_group_bars.each_with_index do |group_bars, group_index|
|
117
|
-
right_y = 0
|
124
|
+
right_y = 0.0
|
118
125
|
group_bars.each_with_index do |bar, index|
|
119
126
|
left_y = group_left_y + (bar_width * index) + padding
|
120
127
|
right_y = left_y + (bar_width * @bar_spacing)
|
121
128
|
|
122
|
-
bottom_x, top_x = conversion.get_top_bottom_scaled(bar.point).sort
|
129
|
+
bottom_x, top_x = conversion.get_top_bottom_scaled(bar.point).sort #: [Float, Float]
|
123
130
|
if bottom_x != top_x
|
124
131
|
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
|
125
132
|
rect_renderer.render(bottom_x + AXIS_MARGIN, left_y, top_x, right_y)
|
@@ -175,10 +182,12 @@ private
|
|
175
182
|
end
|
176
183
|
end
|
177
184
|
|
185
|
+
# @rbs return: Float | Integer
|
178
186
|
def calculate_spacing
|
179
187
|
@group_spacing * (column_count - 1)
|
180
188
|
end
|
181
189
|
|
190
|
+
# @rbs return: Proc
|
182
191
|
def proc_text_metrics
|
183
192
|
->(text) { text_metrics(@marker_font, text) }
|
184
193
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
require_relative 'helper/stacked_mixin'
|
4
6
|
|
5
7
|
#
|
@@ -22,26 +24,28 @@ require_relative 'helper/stacked_mixin'
|
|
22
24
|
# g.write('side_stacked_bar.png')
|
23
25
|
#
|
24
26
|
class Gruff::SideStackedBar < Gruff::SideBar
|
25
|
-
include StackedMixin
|
27
|
+
include Gruff::Base::StackedMixin
|
26
28
|
|
27
29
|
# Spacing factor applied between bars.
|
28
|
-
attr_writer :bar_spacing
|
30
|
+
attr_writer :bar_spacing #: Float | Integer
|
29
31
|
|
30
32
|
# Number of pixels between bar segments.
|
31
|
-
attr_writer :segment_spacing
|
33
|
+
attr_writer :segment_spacing #: Float | Integer
|
32
34
|
|
33
35
|
# Set the number output format string or lambda.
|
34
36
|
# Default is +"%.2f"+.
|
35
|
-
attr_writer :label_formatting
|
37
|
+
attr_writer :label_formatting #: nil | String | Proc
|
36
38
|
|
37
39
|
# Output the values for the bars on a bar graph.
|
38
40
|
# Default is +false+.
|
39
|
-
attr_writer :show_labels_for_bar_values
|
41
|
+
attr_writer :show_labels_for_bar_values #: bool
|
40
42
|
|
41
43
|
# Prevent drawing of column labels left of a side stacked bar graph. Default is +false+.
|
42
|
-
attr_writer :hide_labels
|
44
|
+
attr_writer :hide_labels #: bool
|
43
45
|
|
44
|
-
|
46
|
+
# @rbs target_width: (String | Float | Integer)
|
47
|
+
# @rbs return: void
|
48
|
+
def initialize(target_width = DEFAULT_TARGET_WIDTH)
|
45
49
|
super
|
46
50
|
@has_left_labels = true
|
47
51
|
end
|
@@ -68,7 +72,7 @@ private
|
|
68
72
|
#
|
69
73
|
# Columns sit stacked.
|
70
74
|
bar_width = @graph_height / column_count
|
71
|
-
padding = (bar_width * (1 - @bar_spacing)) / 2
|
75
|
+
padding = (bar_width * (1.0 - @bar_spacing)) / 2
|
72
76
|
|
73
77
|
# Setup the BarConversion Object
|
74
78
|
conversion = Gruff::BarConversion.new(
|
@@ -79,13 +83,13 @@ private
|
|
79
83
|
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
80
84
|
|
81
85
|
normalized_stacked_bars.each_with_index do |stacked_bars, stacked_index|
|
82
|
-
total = 0
|
86
|
+
total = 0.0
|
83
87
|
left_y = @graph_top + (bar_width * stacked_index) + padding
|
84
88
|
right_y = left_y + (bar_width * @bar_spacing)
|
85
89
|
|
86
|
-
top_x = 0
|
90
|
+
top_x = 0.0
|
87
91
|
stacked_bars.each do |bar|
|
88
|
-
next if bar.point == 0
|
92
|
+
next if bar.point.nil? || bar.point == 0
|
89
93
|
|
90
94
|
bottom_x, = conversion.get_top_bottom_scaled(total)
|
91
95
|
bottom_x += @segment_spacing
|
data/lib/gruff/spider.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
# Experimental!!! See also the Net graph.
|
4
6
|
#
|
5
7
|
# Here's how to set up a Gruff::Spider.
|
@@ -16,14 +18,18 @@
|
|
16
18
|
#
|
17
19
|
class Gruff::Spider < Gruff::Base
|
18
20
|
# Hide all text.
|
19
|
-
attr_writer :hide_axes
|
20
|
-
attr_writer :rotation
|
21
|
+
attr_writer :hide_axes #: bool
|
22
|
+
attr_writer :rotation #: Float | Integer
|
21
23
|
|
24
|
+
# @rbs max_value: Float | Integer
|
25
|
+
# @rbs target_width: (String | Float | Integer)
|
26
|
+
# @rbs return: void
|
22
27
|
def initialize(max_value, target_width = 800)
|
23
28
|
super(target_width)
|
24
29
|
@max_value = max_value
|
25
30
|
end
|
26
31
|
|
32
|
+
# @rbs value: bool
|
27
33
|
def hide_text=(value)
|
28
34
|
@hide_title = @hide_text = value
|
29
35
|
end
|
@@ -82,6 +88,7 @@ private
|
|
82
88
|
draw_polygon(center_x, center_y, additive_angle)
|
83
89
|
end
|
84
90
|
|
91
|
+
# @rbs value: nil | Float | Integer
|
85
92
|
def normalize_points(value)
|
86
93
|
value.to_f * @unit_length
|
87
94
|
end
|
data/lib/gruff/stacked_area.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
require_relative 'helper/stacked_mixin'
|
4
6
|
|
5
7
|
#
|
@@ -13,7 +15,7 @@ require_relative 'helper/stacked_mixin'
|
|
13
15
|
# g.write('stacked_area.png')
|
14
16
|
#
|
15
17
|
class Gruff::StackedArea < Gruff::Base
|
16
|
-
include StackedMixin
|
18
|
+
include Gruff::Base::StackedMixin
|
17
19
|
|
18
20
|
# @deprecated
|
19
21
|
def last_series_goes_on_bottom=(_value)
|
@@ -44,6 +46,7 @@ private
|
|
44
46
|
data_points = []
|
45
47
|
|
46
48
|
data_row.points.each_with_index do |data_point, index|
|
49
|
+
data_point = data_point.to_f
|
47
50
|
# Use incremented x and scaled y
|
48
51
|
new_x = @graph_left + (x_increment * index)
|
49
52
|
new_y = @graph_top + (@graph_height - (data_point * @graph_height) - height[index])
|
@@ -58,10 +61,12 @@ private
|
|
58
61
|
|
59
62
|
poly_points = data_points.dup
|
60
63
|
if prev_data_points
|
64
|
+
# steep:ignore:start
|
61
65
|
((prev_data_points.length / 2) - 1).downto(0) do |i|
|
62
66
|
poly_points << prev_data_points[2 * i]
|
63
67
|
poly_points << prev_data_points[(2 * i) + 1]
|
64
68
|
end
|
69
|
+
# steep:ignore:end
|
65
70
|
else
|
66
71
|
poly_points << @graph_right
|
67
72
|
poly_points << (@graph_bottom - 1)
|
data/lib/gruff/stacked_bar.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
require_relative 'helper/stacked_mixin'
|
4
6
|
|
5
7
|
#
|
@@ -13,24 +15,24 @@ require_relative 'helper/stacked_mixin'
|
|
13
15
|
# g.write('stacked_bar.png')
|
14
16
|
#
|
15
17
|
class Gruff::StackedBar < Gruff::Base
|
16
|
-
include StackedMixin
|
18
|
+
include Gruff::Base::StackedMixin
|
17
19
|
|
18
20
|
# Spacing factor applied between bars.
|
19
|
-
attr_writer :bar_spacing
|
21
|
+
attr_writer :bar_spacing #: Float | Integer
|
20
22
|
|
21
23
|
# Number of pixels between bar segments.
|
22
|
-
attr_writer :segment_spacing
|
24
|
+
attr_writer :segment_spacing #: Float | Integer
|
23
25
|
|
24
26
|
# Set the number output format string or lambda.
|
25
27
|
# Default is +"%.2f"+.
|
26
|
-
attr_writer :label_formatting
|
28
|
+
attr_writer :label_formatting #: nil | String | Proc
|
27
29
|
|
28
30
|
# Output the values for the bars on a bar graph.
|
29
31
|
# Default is +false+.
|
30
|
-
attr_writer :show_labels_for_bar_values
|
32
|
+
attr_writer :show_labels_for_bar_values #: bool
|
31
33
|
|
32
34
|
# Prevent drawing of column labels below a stacked bar graph. Default is +false+.
|
33
|
-
attr_writer :hide_labels
|
35
|
+
attr_writer :hide_labels #: bool
|
34
36
|
|
35
37
|
private
|
36
38
|
|
@@ -78,7 +80,7 @@ private
|
|
78
80
|
#
|
79
81
|
# Columns sit stacked.
|
80
82
|
bar_width = @graph_width / column_count
|
81
|
-
padding = (bar_width * (1 - @bar_spacing)) / 2.0
|
83
|
+
padding = (bar_width * (1.0 - @bar_spacing)) / 2.0
|
82
84
|
|
83
85
|
# Setup the BarConversion Object
|
84
86
|
conversion = Gruff::BarConversion.new(
|
@@ -87,13 +89,13 @@ private
|
|
87
89
|
)
|
88
90
|
|
89
91
|
normalized_stacked_bars.each_with_index do |stacked_bars, stacked_index|
|
90
|
-
total = 0
|
92
|
+
total = 0.0
|
91
93
|
left_x = @graph_left + (bar_width * stacked_index) + padding
|
92
94
|
right_x = left_x + (bar_width * @bar_spacing)
|
93
95
|
|
94
|
-
top_y = 0
|
96
|
+
top_y = 0.0
|
95
97
|
stacked_bars.each do |bar|
|
96
|
-
next if bar.point == 0
|
98
|
+
next if bar.point.nil? || bar.point == 0
|
97
99
|
|
98
100
|
bottom_y, = conversion.get_top_bottom_scaled(total)
|
99
101
|
bottom_y -= @segment_spacing
|
@@ -117,18 +119,22 @@ private
|
|
117
119
|
end
|
118
120
|
end
|
119
121
|
|
122
|
+
# @rbs return: bool
|
120
123
|
def hide_labels?
|
121
124
|
@hide_labels
|
122
125
|
end
|
123
126
|
|
127
|
+
# @rbs return: bool
|
124
128
|
def hide_left_label_area?
|
125
129
|
@hide_line_markers && @y_axis_label.nil?
|
126
130
|
end
|
127
131
|
|
132
|
+
# @rbs return: bool
|
128
133
|
def hide_bottom_label_area?
|
129
134
|
hide_labels? && @x_axis_label.nil? && @legend_at_bottom == false
|
130
135
|
end
|
131
136
|
|
137
|
+
# @rbs return: Proc
|
132
138
|
def proc_text_metrics
|
133
139
|
->(text) { text_metrics(@marker_font, text) }
|
134
140
|
end
|
@@ -1,29 +1,63 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rbs_inline: enabled
|
4
|
+
|
3
5
|
module Gruff
|
4
6
|
class Store
|
5
7
|
# @private
|
6
|
-
class BasicData
|
8
|
+
class BasicData
|
9
|
+
attr_accessor :label #: String | Symbol
|
10
|
+
attr_accessor :points #: Array[nil | Float | Integer]
|
11
|
+
attr_accessor :color #: String
|
12
|
+
|
13
|
+
# @rbs label: String | Symbol
|
14
|
+
# @rbs points: Array[nil | Float | Integer] | nil
|
15
|
+
# @rbs color: String
|
7
16
|
def initialize(label, points, color)
|
8
|
-
|
17
|
+
@label = label.to_s
|
18
|
+
@points = Array(points)
|
19
|
+
@color = color
|
20
|
+
end
|
21
|
+
|
22
|
+
alias x_points points
|
23
|
+
|
24
|
+
def y_points
|
25
|
+
raise NotImplementedError, 'x_points is not implemented for BasicData'
|
26
|
+
end
|
27
|
+
|
28
|
+
def coordinates
|
29
|
+
raise NotImplementedError, 'This method is not implemented for BasicData'
|
30
|
+
end
|
31
|
+
|
32
|
+
def coordinate_and_pointsizes
|
33
|
+
raise NotImplementedError, 'This method is not implemented for BasicData'
|
9
34
|
end
|
10
35
|
|
36
|
+
# @rbs return: bool
|
11
37
|
def empty?
|
12
38
|
points.empty?
|
13
39
|
end
|
14
40
|
|
41
|
+
# @rbs return: Integer
|
15
42
|
def columns
|
16
43
|
points.length
|
17
44
|
end
|
18
45
|
|
46
|
+
# @rbs return: Float | Integer
|
19
47
|
def min
|
20
48
|
points.compact.min
|
21
49
|
end
|
50
|
+
alias min_x min
|
22
51
|
|
52
|
+
# @rbs return: Float | Integer
|
23
53
|
def max
|
24
54
|
points.compact.max
|
25
55
|
end
|
56
|
+
alias max_x max
|
26
57
|
|
58
|
+
# @rbs minimum: Float | Integer
|
59
|
+
# @rbs spread: Float | Integer
|
60
|
+
# @rbs return: Gruff::Store::BasicData
|
27
61
|
def normalize(minimum:, spread:)
|
28
62
|
norm_points = points.map do |point|
|
29
63
|
point.nil? ? nil : (point.to_f - minimum.to_f) / spread
|