gruff 0.16.0-java → 0.17.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +5 -2
- data/.gitignore +1 -0
- data/.rubocop.yml +0 -6
- data/CHANGELOG.md +19 -0
- data/gruff.gemspec +2 -3
- data/lib/gruff/area.rb +2 -0
- data/lib/gruff/bar.rb +26 -23
- data/lib/gruff/base.rb +198 -81
- data/lib/gruff/bezier.rb +2 -0
- data/lib/gruff/box_plot.rb +7 -1
- data/lib/gruff/candlestick.rb +21 -13
- data/lib/gruff/dot.rb +4 -5
- data/lib/gruff/helper/bar_conversion.rb +1 -5
- data/lib/gruff/helper/bar_mixin.rb +25 -0
- data/lib/gruff/helper/bar_value_label.rb +0 -22
- data/lib/gruff/helper/stacked_mixin.rb +16 -0
- data/lib/gruff/histogram.rb +8 -4
- data/lib/gruff/line.rb +2 -5
- data/lib/gruff/mini/legend.rb +9 -9
- data/lib/gruff/net.rb +16 -11
- data/lib/gruff/pie.rb +6 -1
- data/lib/gruff/renderer/dot.rb +25 -14
- data/lib/gruff/renderer/renderer.rb +0 -4
- data/lib/gruff/renderer/text.rb +7 -1
- data/lib/gruff/scatter.rb +20 -18
- data/lib/gruff/side_bar.rb +28 -23
- data/lib/gruff/side_stacked_bar.rb +36 -41
- data/lib/gruff/spider.rb +7 -2
- data/lib/gruff/stacked_area.rb +7 -2
- data/lib/gruff/stacked_bar.rb +46 -38
- data/lib/gruff/version.rb +1 -1
- data/lib/gruff.rb +0 -3
- metadata +5 -4
@@ -49,26 +49,4 @@ module Gruff::BarValueLabel
|
|
49
49
|
yield x, left_y, val, metrics.width, metrics.height
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
# @private
|
54
|
-
class StackedBar
|
55
|
-
def initialize
|
56
|
-
@bars = []
|
57
|
-
end
|
58
|
-
|
59
|
-
def add(bar, index)
|
60
|
-
bars = @bars[index] || []
|
61
|
-
bars << bar
|
62
|
-
@bars[index] = bars
|
63
|
-
end
|
64
|
-
|
65
|
-
def prepare_rendering(format, proc_text_metrics, &block)
|
66
|
-
@bars.each do |bars|
|
67
|
-
value = bars.sum(&:value)
|
68
|
-
bar = bars.last
|
69
|
-
bar_value_label = bar.class.new(bar.coordinate, value)
|
70
|
-
bar_value_label.prepare_rendering(format, proc_text_metrics, &block)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
52
|
end
|
@@ -21,4 +21,20 @@ module Gruff::Base::StackedMixin
|
|
21
21
|
|
22
22
|
raise "Can't handle negative values in stacked graph" if minimum_value < 0
|
23
23
|
end
|
24
|
+
|
25
|
+
def normalized_stacked_bars
|
26
|
+
@normalized_stacked_bars ||= begin
|
27
|
+
stacked_bars = Array.new(column_count) { [] }
|
28
|
+
store.norm_data.each_with_index do |data_row, row_index|
|
29
|
+
data_row.points.each_with_index do |data_point, point_index|
|
30
|
+
stacked_bars[point_index] << BarData.new(data_point, store.data[row_index].points[point_index], data_row.color)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
stacked_bars
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @private
|
38
|
+
class BarData < Struct.new(:point, :value, :color)
|
39
|
+
end
|
24
40
|
end
|
data/lib/gruff/histogram.rb
CHANGED
@@ -44,11 +44,15 @@ private
|
|
44
44
|
|
45
45
|
def setup_data
|
46
46
|
@data.each do |(name, data_points, color)|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
if data_points.empty?
|
48
|
+
store.add(name, [], color)
|
49
|
+
else
|
50
|
+
bins, freqs = HistogramArray.new(data_points).histogram(bin_width: @bin_width, min: @minimum_bin, max: @maximum_bin)
|
51
|
+
bins.each_with_index do |bin, index|
|
52
|
+
@labels[index] = bin
|
53
|
+
end
|
54
|
+
store.add(name, freqs, color)
|
50
55
|
end
|
51
|
-
store.add(name, freqs, color)
|
52
56
|
end
|
53
57
|
|
54
58
|
super
|
data/lib/gruff/line.rb
CHANGED
@@ -25,7 +25,7 @@ class Gruff::Line < Gruff::Base
|
|
25
25
|
attr_writer :line_width
|
26
26
|
attr_writer :dot_radius
|
27
27
|
|
28
|
-
# default is +'circle'+, other options include square
|
28
|
+
# default is +'circle'+, other options include +square+ and +diamond+.
|
29
29
|
attr_writer :dot_style
|
30
30
|
|
31
31
|
# Hide parts of the graph to fit more data points, or for a different appearance.
|
@@ -273,10 +273,7 @@ private
|
|
273
273
|
return unless @show_vertical_markers
|
274
274
|
|
275
275
|
(0..@marker_x_count).each do |index|
|
276
|
-
|
277
|
-
|
278
|
-
Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
|
279
|
-
Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x + 1, @graph_bottom, x + 1, @graph_top) if @marker_shadow_color
|
276
|
+
draw_marker_vertical_line(@graph_left + @graph_width - (index * @graph_width / @marker_x_count))
|
280
277
|
end
|
281
278
|
end
|
282
279
|
|
data/lib/gruff/mini/legend.rb
CHANGED
@@ -21,7 +21,7 @@ module Gruff
|
|
21
21
|
|
22
22
|
@legend_labels = store.data.map(&:label)
|
23
23
|
|
24
|
-
legend_height =
|
24
|
+
legend_height = scale((store.length * calculate_line_height) + @top_margin + @bottom_margin)
|
25
25
|
|
26
26
|
@original_rows = @raw_rows
|
27
27
|
@original_columns = @raw_columns
|
@@ -32,7 +32,7 @@ module Gruff
|
|
32
32
|
@columns += calculate_legend_width + @left_margin
|
33
33
|
else
|
34
34
|
font = @legend_font.dup
|
35
|
-
font.size =
|
35
|
+
font.size = scale(font.size)
|
36
36
|
@rows += store.length * calculate_caps_height(font) * 1.7
|
37
37
|
end
|
38
38
|
|
@@ -45,7 +45,7 @@ module Gruff
|
|
45
45
|
|
46
46
|
def calculate_legend_width
|
47
47
|
width = @legend_labels.map { |label| calculate_width(@legend_font, label) }.max
|
48
|
-
|
48
|
+
scale(width + (40 * 1.7))
|
49
49
|
end
|
50
50
|
|
51
51
|
##
|
@@ -69,9 +69,9 @@ module Gruff
|
|
69
69
|
|
70
70
|
@legend_labels.each_with_index do |legend_label, index|
|
71
71
|
# Draw label
|
72
|
-
label = truncate_legend_label(legend_label)
|
73
|
-
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
|
74
72
|
x_offset = current_x_offset + (legend_square_width * 1.7)
|
73
|
+
label = truncate_legend_label(legend_label, x_offset)
|
74
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
|
75
75
|
text_renderer.add_to_render_queue(@raw_columns, 1.0, x_offset, current_y_offset, Magick::WestGravity)
|
76
76
|
|
77
77
|
# Now draw box with color of this dataset
|
@@ -90,13 +90,13 @@ module Gruff
|
|
90
90
|
#
|
91
91
|
# Department of Hu...
|
92
92
|
|
93
|
-
def truncate_legend_label(label)
|
93
|
+
def truncate_legend_label(label, x_offset)
|
94
94
|
truncated_label = label.to_s
|
95
95
|
|
96
96
|
font = @legend_font.dup
|
97
|
-
font.size =
|
98
|
-
max_width = @columns -
|
99
|
-
while calculate_width(font, truncated_label) > max_width && truncated_label.length > 1
|
97
|
+
font.size = scale(font.size)
|
98
|
+
max_width = @columns - scale(x_offset) - @right_margin
|
99
|
+
while calculate_width(font, "#{truncated_label}...") > max_width && truncated_label.length > 1
|
100
100
|
truncated_label = truncated_label[0..truncated_label.length - 2]
|
101
101
|
end
|
102
102
|
truncated_label + (truncated_label.length < label.to_s.length ? '...' : '')
|
data/lib/gruff/net.rb
CHANGED
@@ -43,6 +43,21 @@ private
|
|
43
43
|
@marker_font.bold = true
|
44
44
|
end
|
45
45
|
|
46
|
+
def setup_drawing
|
47
|
+
@center_labels_over_point = false
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup_graph_measurements
|
52
|
+
super
|
53
|
+
|
54
|
+
@radius = @graph_height / 2.0
|
55
|
+
@circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 2.5), 5.0)
|
56
|
+
@stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 4.0), 5.0)
|
57
|
+
@center_x = @graph_left + (@graph_width / 2.0)
|
58
|
+
@center_y = @graph_top + (@graph_height / 2.0) + 10
|
59
|
+
end
|
60
|
+
|
46
61
|
def draw_graph
|
47
62
|
store.norm_data.each do |data_row|
|
48
63
|
data_row.points.each_with_index do |data_point, index|
|
@@ -70,16 +85,6 @@ private
|
|
70
85
|
end
|
71
86
|
end
|
72
87
|
|
73
|
-
def setup_drawing
|
74
|
-
super
|
75
|
-
|
76
|
-
@radius = @graph_height / 2.0
|
77
|
-
@circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 2.5), 5.0)
|
78
|
-
@stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 4), 5.0)
|
79
|
-
@center_x = @graph_left + (@graph_width / 2.0)
|
80
|
-
@center_y = @graph_top + (@graph_height / 2.0) + 10
|
81
|
-
end
|
82
|
-
|
83
88
|
# the lines connecting in the center, with the first line vertical
|
84
89
|
def draw_line_markers
|
85
90
|
return if @hide_line_markers
|
@@ -102,6 +107,6 @@ private
|
|
102
107
|
x = x_offset + ((radius + LABEL_MARGIN) * Math.sin(deg2rad(angle)))
|
103
108
|
y = y_offset - ((radius + LABEL_MARGIN) * Math.cos(deg2rad(angle)))
|
104
109
|
|
105
|
-
draw_label_at(1.0, 1.0, x, y, amount, Magick::CenterGravity)
|
110
|
+
draw_label_at(1.0, 1.0, x, y, amount, gravity: Magick::CenterGravity)
|
106
111
|
end
|
107
112
|
end
|
data/lib/gruff/pie.rb
CHANGED
@@ -61,6 +61,11 @@ private
|
|
61
61
|
@label_formatting = ->(value, percentage) { @show_values_as_labels ? value.to_s : "#{percentage}%" }
|
62
62
|
end
|
63
63
|
|
64
|
+
def setup_drawing
|
65
|
+
@center_labels_over_point = false
|
66
|
+
super
|
67
|
+
end
|
68
|
+
|
64
69
|
def draw_graph
|
65
70
|
slices.each do |slice|
|
66
71
|
if slice.value > 0
|
@@ -136,7 +141,7 @@ private
|
|
136
141
|
if slice.percentage >= @hide_labels_less_than
|
137
142
|
x, y = label_coordinates_for slice
|
138
143
|
label = @label_formatting.call(slice.value, slice.percentage)
|
139
|
-
draw_label_at(1.0, 1.0, x, y, label, Magick::CenterGravity)
|
144
|
+
draw_label_at(1.0, 1.0, x, y, label, gravity: Magick::CenterGravity)
|
140
145
|
end
|
141
146
|
end
|
142
147
|
|
data/lib/gruff/renderer/dot.rb
CHANGED
@@ -11,31 +11,42 @@ module Gruff
|
|
11
11
|
@opacity = opacity
|
12
12
|
end
|
13
13
|
|
14
|
-
def render(new_x, new_y,
|
15
|
-
|
14
|
+
def render(new_x, new_y, radius)
|
15
|
+
@renderer.draw.push
|
16
16
|
@renderer.draw.stroke_width(@width)
|
17
17
|
@renderer.draw.stroke(@color)
|
18
18
|
@renderer.draw.fill(@color)
|
19
19
|
@renderer.draw.fill_opacity(@opacity)
|
20
|
-
|
21
|
-
|
20
|
+
case @style.to_sym
|
21
|
+
when :square
|
22
|
+
square(new_x, new_y, radius)
|
23
|
+
when :diamond
|
24
|
+
diamond(new_x, new_y, radius)
|
22
25
|
else
|
23
|
-
circle(new_x, new_y,
|
26
|
+
circle(new_x, new_y, radius)
|
24
27
|
end
|
25
|
-
|
28
|
+
@renderer.draw.pop
|
26
29
|
end
|
27
30
|
|
28
|
-
def circle(new_x, new_y,
|
29
|
-
@renderer.draw.circle(new_x, new_y, new_x -
|
31
|
+
def circle(new_x, new_y, radius)
|
32
|
+
@renderer.draw.circle(new_x, new_y, new_x - radius, new_y)
|
30
33
|
end
|
31
34
|
|
32
|
-
def square(new_x, new_y,
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
corner4 = new_y + offset
|
35
|
+
def square(new_x, new_y, radius)
|
36
|
+
corner1 = new_x - radius
|
37
|
+
corner2 = new_y - radius
|
38
|
+
corner3 = new_x + radius
|
39
|
+
corner4 = new_y + radius
|
38
40
|
@renderer.draw.rectangle(corner1, corner2, corner3, corner4)
|
39
41
|
end
|
42
|
+
|
43
|
+
def diamond(new_x, new_y, radius)
|
44
|
+
polygon = []
|
45
|
+
polygon += [new_x - radius, new_y]
|
46
|
+
polygon += [new_x, new_y + radius]
|
47
|
+
polygon += [new_x + radius, new_y]
|
48
|
+
polygon += [new_x, new_y - radius]
|
49
|
+
@renderer.draw.polygon(*polygon)
|
50
|
+
end
|
40
51
|
end
|
41
52
|
end
|
data/lib/gruff/renderer/text.rb
CHANGED
@@ -25,6 +25,7 @@ module Gruff
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def render(width, height, x, y, gravity = Magick::NorthGravity)
|
28
|
+
@renderer.draw.push
|
28
29
|
@renderer.draw.rotation = @rotation if @rotation
|
29
30
|
@renderer.draw.fill = @font.color
|
30
31
|
@renderer.draw.stroke = 'transparent'
|
@@ -37,9 +38,11 @@ module Gruff
|
|
37
38
|
x, y,
|
38
39
|
@text, @renderer.scale)
|
39
40
|
@renderer.draw.rotation = -@rotation if @rotation
|
41
|
+
@renderer.draw.pop
|
40
42
|
end
|
41
43
|
|
42
44
|
def metrics
|
45
|
+
@renderer.draw.push
|
43
46
|
@renderer.draw.font = @font.file_path
|
44
47
|
@renderer.draw.font_weight = @font.weight
|
45
48
|
@renderer.draw.pointsize = @font.size
|
@@ -50,7 +53,10 @@ module Gruff
|
|
50
53
|
# So, in here, it just escape % in order to avoid SEGV.
|
51
54
|
text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
|
52
55
|
|
53
|
-
@renderer.draw.get_type_metrics(@renderer.image, text)
|
56
|
+
metrics = @renderer.draw.get_type_metrics(@renderer.image, text)
|
57
|
+
@renderer.draw.pop
|
58
|
+
|
59
|
+
metrics
|
54
60
|
end
|
55
61
|
end
|
56
62
|
end
|
data/lib/gruff/scatter.rb
CHANGED
@@ -114,20 +114,9 @@ private
|
|
114
114
|
@x_label_margin = nil
|
115
115
|
end
|
116
116
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
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
|
117
|
+
def setup_drawing
|
118
|
+
@center_labels_over_point = false
|
119
|
+
super
|
131
120
|
end
|
132
121
|
|
133
122
|
def setup_data
|
@@ -147,6 +136,22 @@ private
|
|
147
136
|
super
|
148
137
|
end
|
149
138
|
|
139
|
+
def draw_graph
|
140
|
+
store.norm_data.each do |data_row|
|
141
|
+
data_row.coordinates.each do |x_value, y_value|
|
142
|
+
next if y_value.nil? || x_value.nil?
|
143
|
+
|
144
|
+
new_x = get_x_coord(x_value, @graph_width, @graph_left)
|
145
|
+
new_y = @graph_top + (@graph_height - (y_value * @graph_height))
|
146
|
+
|
147
|
+
# Reset each time to avoid thin-line errors
|
148
|
+
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
149
|
+
circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
|
150
|
+
Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
150
155
|
def calculate_spread
|
151
156
|
super
|
152
157
|
@x_spread = @maximum_x_value.to_f - @minimum_x_value.to_f
|
@@ -170,10 +175,7 @@ private
|
|
170
175
|
(0..marker_x_count).each do |index|
|
171
176
|
# TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
|
172
177
|
if @show_vertical_markers
|
173
|
-
|
174
|
-
|
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
|
178
|
+
draw_marker_vertical_line(@graph_left + @graph_width - (index * increment_x_scaled))
|
177
179
|
end
|
178
180
|
|
179
181
|
unless @hide_line_numbers
|
data/lib/gruff/side_bar.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'helper/bar_mixin'
|
4
|
+
|
3
5
|
# Graph with individual horizontal bars instead of vertical bars.
|
4
6
|
#
|
5
7
|
# Here's how to set up a Gruff::SideBar.
|
@@ -19,6 +21,8 @@
|
|
19
21
|
# g.write('sidebar.png')
|
20
22
|
#
|
21
23
|
class Gruff::SideBar < Gruff::Base
|
24
|
+
include BarMixin
|
25
|
+
|
22
26
|
# Spacing factor applied between bars.
|
23
27
|
attr_writer :bar_spacing
|
24
28
|
|
@@ -79,8 +83,6 @@ private
|
|
79
83
|
return if @hide_line_markers
|
80
84
|
|
81
85
|
if @show_labels_for_bar_values
|
82
|
-
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
83
|
-
|
84
86
|
if maximum_value >= 0
|
85
87
|
_, metrics = Gruff::BarValueLabel.metrics(maximum_value, @label_formatting, proc_text_metrics)
|
86
88
|
@graph_right -= metrics.width
|
@@ -109,32 +111,33 @@ private
|
|
109
111
|
minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
|
110
112
|
)
|
111
113
|
|
112
|
-
|
114
|
+
group_spacing = @group_spacing * @scale
|
115
|
+
group_left_y = @graph_top
|
113
116
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
|
117
|
+
normalized_group_bars.each_with_index do |group_bars, group_index|
|
118
|
+
right_y = 0
|
119
|
+
group_bars.each_with_index do |bar, index|
|
120
|
+
left_y = group_left_y + (bar_width * index) + padding
|
119
121
|
right_y = left_y + (bar_width * @bar_spacing)
|
120
122
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
# Calculate center based on bar_width and current row
|
127
|
-
label_center = left_y + (bars_width / 2.0)
|
123
|
+
bottom_x, top_x = conversion.get_top_bottom_scaled(bar.point).sort
|
124
|
+
if bar.point != 0
|
125
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
|
126
|
+
rect_renderer.render(bottom_x + AXIS_MARGIN, left_y, top_x, right_y)
|
127
|
+
end
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
if @show_labels_for_bar_values
|
132
|
-
bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
|
129
|
+
if @show_labels_for_bar_values && bar.value
|
130
|
+
bar_value_label = Gruff::BarValueLabel::SideBar.new([bottom_x, left_y, top_x, right_y], bar.value)
|
133
131
|
bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
|
134
132
|
draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
|
135
133
|
end
|
136
134
|
end
|
137
135
|
end
|
136
|
+
|
137
|
+
label_center = group_left_y + (bars_width / 2.0)
|
138
|
+
draw_label(label_center, group_index)
|
139
|
+
|
140
|
+
group_left_y = right_y + padding + group_spacing
|
138
141
|
end
|
139
142
|
end
|
140
143
|
|
@@ -151,9 +154,7 @@ private
|
|
151
154
|
(0..number_of_lines).each do |index|
|
152
155
|
line_diff = (@graph_right - @graph_left) / number_of_lines
|
153
156
|
x = @graph_right - (line_diff * index) - 1
|
154
|
-
|
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
|
157
|
+
draw_marker_vertical_line(x)
|
157
158
|
|
158
159
|
unless @hide_line_numbers
|
159
160
|
diff = index - number_of_lines
|
@@ -170,11 +171,15 @@ private
|
|
170
171
|
|
171
172
|
def draw_label(y_offset, index)
|
172
173
|
draw_unique_label(index) do
|
173
|
-
draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
|
174
|
+
draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], gravity: Magick::EastGravity)
|
174
175
|
end
|
175
176
|
end
|
176
177
|
|
177
178
|
def calculate_spacing
|
178
179
|
@scale * @group_spacing * (column_count - 1)
|
179
180
|
end
|
181
|
+
|
182
|
+
def proc_text_metrics
|
183
|
+
->(text) { text_metrics(@marker_font, text) }
|
184
|
+
end
|
180
185
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'helper/stacked_mixin'
|
4
|
+
|
3
5
|
#
|
4
6
|
# New gruff graph type added to enable sideways stacking bar charts
|
5
7
|
# (basically looks like a x/y flip of a standard stacking bar chart)
|
@@ -66,50 +68,43 @@ private
|
|
66
68
|
#
|
67
69
|
# Columns sit stacked.
|
68
70
|
bar_width = @graph_height / column_count
|
69
|
-
height = Array.new(column_count, 0)
|
70
|
-
length = Array.new(column_count, @graph_left)
|
71
71
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
|
99
|
-
rect_renderer.render(left_x, left_y, right_x, right_y)
|
100
|
-
# Calculate center based on bar_width and current row
|
101
|
-
end
|
102
|
-
# we still need to draw the labels
|
103
|
-
# Calculate center based on bar_width and current row
|
104
|
-
label_center = left_y + (bar_width / 2.0)
|
105
|
-
draw_label(label_center, point_index)
|
72
|
+
|
73
|
+
# Setup the BarConversion Object
|
74
|
+
conversion = Gruff::BarConversion.new(
|
75
|
+
top: @graph_right, bottom: @graph_left,
|
76
|
+
minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
|
77
|
+
)
|
78
|
+
|
79
|
+
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
80
|
+
|
81
|
+
normalized_stacked_bars.each_with_index do |stacked_bars, stacked_index|
|
82
|
+
total = 0
|
83
|
+
left_y = @graph_top + (bar_width * stacked_index) + padding
|
84
|
+
right_y = left_y + (bar_width * @bar_spacing)
|
85
|
+
|
86
|
+
top_x = 0
|
87
|
+
stacked_bars.each do |bar|
|
88
|
+
next if bar.point == 0
|
89
|
+
|
90
|
+
bottom_x, = conversion.get_top_bottom_scaled(total)
|
91
|
+
bottom_x += @segment_spacing
|
92
|
+
top_x, = conversion.get_top_bottom_scaled(total + bar.point)
|
93
|
+
|
94
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
|
95
|
+
rect_renderer.render(bottom_x, left_y, top_x, right_y)
|
96
|
+
|
97
|
+
total += bar.point
|
106
98
|
end
|
107
|
-
end
|
108
99
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
100
|
+
label_center = left_y + (bar_width / 2.0)
|
101
|
+
draw_label(label_center, stacked_index)
|
102
|
+
|
103
|
+
if @show_labels_for_bar_values
|
104
|
+
bar_value_label = Gruff::BarValueLabel::SideBar.new([@graph_left, left_y, top_x, right_y], stacked_bars.sum(&:value))
|
105
|
+
bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
|
106
|
+
draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
|
107
|
+
end
|
113
108
|
end
|
114
109
|
end
|
115
110
|
end
|
data/lib/gruff/spider.rb
CHANGED
@@ -46,6 +46,11 @@ private
|
|
46
46
|
@hide_line_markers.freeze
|
47
47
|
end
|
48
48
|
|
49
|
+
def setup_drawing
|
50
|
+
@center_labels_over_point = false
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
49
54
|
def setup_graph_measurements
|
50
55
|
super
|
51
56
|
|
@@ -82,7 +87,7 @@ private
|
|
82
87
|
end
|
83
88
|
|
84
89
|
def normalize_points(value)
|
85
|
-
value * @unit_length
|
90
|
+
value.to_f * @unit_length
|
86
91
|
end
|
87
92
|
|
88
93
|
def draw_label(center_x, center_y, angle, radius, amount)
|
@@ -107,7 +112,7 @@ private
|
|
107
112
|
x = x_offset + ((radius + r_offset) * Math.cos(angle))
|
108
113
|
y = y_offset + ((radius + r_offset) * Math.sin(angle))
|
109
114
|
|
110
|
-
draw_label_at(metrics.width, metrics.height, x, y, amount, Magick::CenterGravity)
|
115
|
+
draw_label_at(metrics.width, metrics.height, x, y, amount, gravity: Magick::CenterGravity)
|
111
116
|
end
|
112
117
|
|
113
118
|
def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
|
data/lib/gruff/stacked_area.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'helper/stacked_mixin'
|
4
|
+
|
3
5
|
#
|
4
6
|
# Here's how to set up a Gruff::StackedArea.
|
5
7
|
#
|
@@ -35,9 +37,10 @@ private
|
|
35
37
|
|
36
38
|
height = Array.new(column_count, 0)
|
37
39
|
|
38
|
-
|
40
|
+
prev_data_points = nil
|
39
41
|
store.norm_data.each do |data_row|
|
40
|
-
|
42
|
+
next if data_row.points.empty?
|
43
|
+
|
41
44
|
data_points = []
|
42
45
|
|
43
46
|
data_row.points.each_with_index do |data_point, index|
|
@@ -69,6 +72,8 @@ private
|
|
69
72
|
poly_points << data_points[1]
|
70
73
|
|
71
74
|
Gruff::Renderer::Polygon.new(renderer, color: data_row.color).render(poly_points)
|
75
|
+
|
76
|
+
prev_data_points = data_points
|
72
77
|
end
|
73
78
|
end
|
74
79
|
end
|