gruff 0.15.0-java → 0.16.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 +17 -4
- data/.rubocop.yml +0 -6
- data/CHANGELOG.md +26 -0
- data/README.md +10 -3
- data/gruff.gemspec +1 -1
- data/lib/gruff/accumulator_bar.rb +1 -1
- data/lib/gruff/area.rb +4 -4
- data/lib/gruff/bar.rb +28 -9
- data/lib/gruff/base.rb +109 -118
- data/lib/gruff/bezier.rb +2 -2
- data/lib/gruff/box_plot.rb +174 -0
- data/lib/gruff/bullet.rb +5 -5
- data/lib/gruff/candlestick.rb +112 -0
- data/lib/gruff/dot.rb +10 -10
- data/lib/gruff/font.rb +3 -0
- data/lib/gruff/helper/bar_conversion.rb +5 -5
- data/lib/gruff/helper/bar_value_label.rb +27 -24
- data/lib/gruff/helper/stacked_mixin.rb +3 -1
- data/lib/gruff/histogram.rb +1 -1
- data/lib/gruff/line.rb +48 -42
- data/lib/gruff/mini/legend.rb +4 -4
- data/lib/gruff/net.rb +7 -7
- data/lib/gruff/patch/string.rb +1 -0
- data/lib/gruff/pie.rb +20 -11
- data/lib/gruff/renderer/dash_line.rb +3 -2
- data/lib/gruff/renderer/dot.rb +3 -1
- data/lib/gruff/renderer/line.rb +1 -3
- data/lib/gruff/renderer/rectangle.rb +6 -2
- data/lib/gruff/scatter.rb +52 -46
- data/lib/gruff/side_bar.rb +43 -14
- data/lib/gruff/side_stacked_bar.rb +20 -27
- data/lib/gruff/spider.rb +46 -13
- data/lib/gruff/stacked_area.rb +11 -6
- data/lib/gruff/stacked_bar.rb +36 -14
- data/lib/gruff/version.rb +1 -1
- data/lib/gruff.rb +9 -9
- metadata +4 -4
- data/lib/gruff/scene.rb +0 -208
- data/lib/gruff/store/custom_data.rb +0 -36
@@ -3,17 +3,18 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::DashLine
|
6
|
-
def initialize(renderer, color:, width:)
|
6
|
+
def initialize(renderer, color:, width:, dasharray: [10, 20])
|
7
7
|
@renderer = renderer
|
8
8
|
@color = color
|
9
9
|
@width = width
|
10
|
+
@dasharray = dasharray
|
10
11
|
end
|
11
12
|
|
12
13
|
def render(start_x, start_y, end_x, end_y)
|
13
14
|
@renderer.draw.push
|
14
15
|
@renderer.draw.stroke_color(@color)
|
15
16
|
@renderer.draw.fill_opacity(0.0)
|
16
|
-
@renderer.draw.stroke_dasharray(
|
17
|
+
@renderer.draw.stroke_dasharray(*@dasharray)
|
17
18
|
@renderer.draw.stroke_width(@width)
|
18
19
|
@renderer.draw.line(start_x, start_y, end_x, end_y)
|
19
20
|
@renderer.draw.pop
|
data/lib/gruff/renderer/dot.rb
CHANGED
@@ -3,11 +3,12 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Dot
|
6
|
-
def initialize(renderer, style, color:, width: 1.0)
|
6
|
+
def initialize(renderer, style, color:, width: 1.0, opacity: 1.0)
|
7
7
|
@renderer = renderer
|
8
8
|
@style = style
|
9
9
|
@color = color
|
10
10
|
@width = width
|
11
|
+
@opacity = opacity
|
11
12
|
end
|
12
13
|
|
13
14
|
def render(new_x, new_y, circle_radius)
|
@@ -15,6 +16,7 @@ module Gruff
|
|
15
16
|
@renderer.draw.stroke_width(@width)
|
16
17
|
@renderer.draw.stroke(@color)
|
17
18
|
@renderer.draw.fill(@color)
|
19
|
+
@renderer.draw.fill_opacity(@opacity)
|
18
20
|
if @style.to_s == 'square'
|
19
21
|
square(new_x, new_y, circle_radius)
|
20
22
|
else
|
data/lib/gruff/renderer/line.rb
CHANGED
@@ -5,16 +5,14 @@ module Gruff
|
|
5
5
|
class Renderer::Line
|
6
6
|
EPSILON = 0.001
|
7
7
|
|
8
|
-
def initialize(renderer, color:, width: nil
|
8
|
+
def initialize(renderer, color:, width: nil)
|
9
9
|
@renderer = renderer
|
10
10
|
@color = color
|
11
11
|
@width = width
|
12
|
-
@shadow_color = shadow_color
|
13
12
|
end
|
14
13
|
|
15
14
|
def render(start_x, start_y, end_x, end_y)
|
16
15
|
render_line(start_x, start_y, end_x, end_y, @color)
|
17
|
-
render_line(start_x, start_y + 1, end_x, end_y + 1, @shadow_color) if @shadow_color
|
18
16
|
end
|
19
17
|
|
20
18
|
private
|
@@ -3,14 +3,18 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Rectangle
|
6
|
-
def initialize(renderer, color: nil)
|
6
|
+
def initialize(renderer, color: nil, width: 1.0, opacity: 1.0)
|
7
7
|
@renderer = renderer
|
8
8
|
@color = color
|
9
|
+
@width = width
|
10
|
+
@opacity = opacity
|
9
11
|
end
|
10
12
|
|
11
13
|
def render(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
12
14
|
@renderer.draw.push
|
13
|
-
@renderer.draw.
|
15
|
+
@renderer.draw.stroke_width(@width)
|
16
|
+
@renderer.draw.stroke(@color) if @width > 1.0
|
17
|
+
@renderer.draw.fill_opacity(@opacity)
|
14
18
|
@renderer.draw.fill(@color) if @color
|
15
19
|
@renderer.draw.rectangle(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
16
20
|
@renderer.draw.pop
|
data/lib/gruff/scatter.rb
CHANGED
@@ -115,15 +115,12 @@ private
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def draw_graph
|
118
|
-
# Check to see if more than one datapoint was given. NaN can result otherwise.
|
119
|
-
@x_increment = @x_spread > 1 ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
|
120
|
-
|
121
118
|
store.norm_data.each do |data_row|
|
122
119
|
data_row.coordinates.each do |x_value, y_value|
|
123
120
|
next if y_value.nil? || x_value.nil?
|
124
121
|
|
125
122
|
new_x = get_x_coord(x_value, @graph_width, @graph_left)
|
126
|
-
new_y = @graph_top + (@graph_height - y_value * @graph_height)
|
123
|
+
new_y = @graph_top + (@graph_height - (y_value * @graph_height))
|
127
124
|
|
128
125
|
# Reset each time to avoid thin-line errors
|
129
126
|
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
@@ -134,17 +131,19 @@ private
|
|
134
131
|
end
|
135
132
|
|
136
133
|
def setup_data
|
137
|
-
# Update the global min/max values for the x data
|
138
|
-
@maximum_x_value ||= store.max_x
|
139
|
-
@minimum_x_value ||= store.min_x
|
140
|
-
|
141
|
-
super
|
142
|
-
end
|
143
|
-
|
144
|
-
def setup_drawing
|
145
134
|
# TODO: Need to get x-axis labels working. Current behavior will be to not allow.
|
146
135
|
@labels = {}
|
147
136
|
|
137
|
+
# Update the global min/max values for the x data
|
138
|
+
@maximum_x_value = (@maximum_x_value || store.max_x).to_f
|
139
|
+
@minimum_x_value = (@minimum_x_value || store.min_x).to_f
|
140
|
+
|
141
|
+
if @x_axis_increment
|
142
|
+
# TODO: Make this work for negative values
|
143
|
+
@maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment.to_f].max
|
144
|
+
@minimum_x_value = @minimum_x_value.floor
|
145
|
+
end
|
146
|
+
|
148
147
|
super
|
149
148
|
end
|
150
149
|
|
@@ -165,49 +164,24 @@ private
|
|
165
164
|
super
|
166
165
|
return if @hide_line_markers
|
167
166
|
|
168
|
-
|
169
|
-
# TODO: Do the same for larger numbers...100, 75, 50, 25
|
170
|
-
if @marker_x_count.nil?
|
171
|
-
(3..7).each do |lines|
|
172
|
-
if @x_spread % lines == 0.0
|
173
|
-
@marker_x_count = lines
|
174
|
-
break
|
175
|
-
end
|
176
|
-
end
|
177
|
-
@marker_x_count ||= 4
|
178
|
-
end
|
179
|
-
@x_increment = @x_spread > 0 ? (@x_spread / @marker_x_count) : 1
|
180
|
-
unless @disable_significant_rounding_x_axis
|
181
|
-
@x_increment = significant(@x_increment)
|
182
|
-
end
|
183
|
-
else
|
184
|
-
# TODO: Make this work for negative values
|
185
|
-
@maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment].max
|
186
|
-
@minimum_x_value = @minimum_x_value.floor
|
187
|
-
calculate_spread
|
188
|
-
normalize
|
189
|
-
|
190
|
-
@marker_x_count = (@x_spread / @x_axis_increment).to_i
|
191
|
-
@x_increment = @x_axis_increment
|
192
|
-
end
|
193
|
-
increment_x_scaled = @graph_width.to_f / (@x_spread / @x_increment)
|
167
|
+
increment_x_scaled = @graph_width / (@x_spread / x_increment)
|
194
168
|
|
195
169
|
# Draw vertical line markers and annotate with numbers
|
196
|
-
(0
|
170
|
+
(0..marker_x_count).each do |index|
|
197
171
|
# TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
|
198
172
|
if @show_vertical_markers
|
199
|
-
x = @graph_left + @graph_width - index
|
173
|
+
x = @graph_left + @graph_width - (index * increment_x_scaled)
|
200
174
|
|
201
|
-
|
202
|
-
|
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
|
203
177
|
end
|
204
178
|
|
205
179
|
unless @hide_line_numbers
|
206
|
-
marker_label = BigDecimal(index.to_s) * BigDecimal(
|
180
|
+
marker_label = (BigDecimal(index.to_s) * BigDecimal(x_increment.to_s)) + BigDecimal(@minimum_x_value.to_s)
|
207
181
|
y_offset = @graph_bottom + (@x_label_margin || LABEL_MARGIN)
|
208
|
-
x_offset = get_x_coord(index
|
182
|
+
x_offset = get_x_coord(index, increment_x_scaled, @graph_left)
|
209
183
|
|
210
|
-
label = x_axis_label(marker_label,
|
184
|
+
label = x_axis_label(marker_label, x_increment)
|
211
185
|
rotation = -90.0 if @use_vertical_x_labels
|
212
186
|
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font, rotation: rotation)
|
213
187
|
text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
|
@@ -216,6 +190,38 @@ private
|
|
216
190
|
end
|
217
191
|
|
218
192
|
def get_x_coord(x_data_point, width, offset)
|
219
|
-
x_data_point * width + offset
|
193
|
+
(x_data_point * width) + offset
|
194
|
+
end
|
195
|
+
|
196
|
+
def marker_x_count
|
197
|
+
# TODO: Do the same for larger numbers...100, 75, 50, 25
|
198
|
+
@marker_x_count ||= begin
|
199
|
+
if @x_axis_increment.nil?
|
200
|
+
count = nil
|
201
|
+
(3..7).each do |lines|
|
202
|
+
if @x_spread % lines == 0.0
|
203
|
+
count = lines and break
|
204
|
+
end
|
205
|
+
end
|
206
|
+
count || 4
|
207
|
+
else
|
208
|
+
(@x_spread / @x_axis_increment).to_i
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def x_increment
|
214
|
+
@x_increment ||= begin
|
215
|
+
if @x_axis_increment.nil?
|
216
|
+
increment = @x_spread > 0 ? (@x_spread / marker_x_count) : 1
|
217
|
+
unless @disable_significant_rounding_x_axis
|
218
|
+
increment = significant(increment)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
increment = @x_axis_increment
|
222
|
+
end
|
223
|
+
|
224
|
+
increment
|
225
|
+
end
|
220
226
|
end
|
221
227
|
end
|
data/lib/gruff/side_bar.rb
CHANGED
@@ -36,6 +36,15 @@ class Gruff::SideBar < Gruff::Base
|
|
36
36
|
# Prevent drawing of column labels left of a side bar graph. Default is +false+.
|
37
37
|
attr_writer :hide_labels
|
38
38
|
|
39
|
+
# Value to avoid completely overwriting the coordinate axis
|
40
|
+
AXIS_MARGIN = 0.5
|
41
|
+
private_constant :AXIS_MARGIN
|
42
|
+
|
43
|
+
def initialize(*)
|
44
|
+
super
|
45
|
+
@has_left_labels = true
|
46
|
+
end
|
47
|
+
|
39
48
|
# With Side Bars use the data label for the marker value to the left of the bar.
|
40
49
|
# @deprecated
|
41
50
|
def use_data_label=(_value)
|
@@ -51,7 +60,6 @@ private
|
|
51
60
|
@label_formatting = nil
|
52
61
|
@show_labels_for_bar_values = false
|
53
62
|
@hide_labels = false
|
54
|
-
@has_left_labels = true
|
55
63
|
end
|
56
64
|
|
57
65
|
def hide_labels?
|
@@ -59,20 +67,39 @@ private
|
|
59
67
|
end
|
60
68
|
|
61
69
|
def hide_left_label_area?
|
62
|
-
hide_labels?
|
70
|
+
hide_labels? && @y_axis_label.nil?
|
63
71
|
end
|
64
72
|
|
65
73
|
def hide_bottom_label_area?
|
66
|
-
@hide_line_markers
|
74
|
+
@hide_line_markers && @x_axis_label.nil? && @legend_at_bottom == false
|
67
75
|
end
|
68
76
|
|
69
|
-
|
70
|
-
|
77
|
+
def setup_graph_measurements
|
78
|
+
super
|
79
|
+
return if @hide_line_markers
|
80
|
+
|
81
|
+
if @show_labels_for_bar_values
|
82
|
+
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
83
|
+
|
84
|
+
if maximum_value >= 0
|
85
|
+
_, metrics = Gruff::BarValueLabel.metrics(maximum_value, @label_formatting, proc_text_metrics)
|
86
|
+
@graph_right -= metrics.width
|
87
|
+
end
|
88
|
+
|
89
|
+
if minimum_value < 0
|
90
|
+
_, metrics = Gruff::BarValueLabel.metrics(minimum_value, @label_formatting, proc_text_metrics)
|
91
|
+
width = metrics.width + LABEL_MARGIN
|
92
|
+
@graph_left += width - @graph_left if width > @graph_left
|
93
|
+
end
|
94
|
+
|
95
|
+
@graph_width = @graph_right - @graph_left
|
96
|
+
end
|
97
|
+
end
|
71
98
|
|
72
99
|
def draw_graph
|
73
100
|
# Setup spacing.
|
74
101
|
#
|
75
|
-
bars_width = (@graph_height - calculate_spacing) / column_count
|
102
|
+
bars_width = (@graph_height - calculate_spacing) / column_count
|
76
103
|
bar_width = bars_width / store.length
|
77
104
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
78
105
|
|
@@ -82,12 +109,14 @@ private
|
|
82
109
|
minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
|
83
110
|
)
|
84
111
|
|
112
|
+
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
113
|
+
|
85
114
|
store.norm_data.each_with_index do |data_row, row_index|
|
86
115
|
data_row.points.each_with_index do |data_point, point_index|
|
87
116
|
group_spacing = @group_spacing * @scale * point_index
|
88
117
|
|
89
118
|
left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
|
90
|
-
right_y = left_y + bar_width * @bar_spacing
|
119
|
+
right_y = left_y + (bar_width * @bar_spacing)
|
91
120
|
|
92
121
|
left_x, right_x = conversion.get_top_bottom_scaled(data_point).sort
|
93
122
|
|
@@ -95,14 +124,14 @@ private
|
|
95
124
|
rect_renderer.render(left_x + AXIS_MARGIN, left_y, right_x + AXIS_MARGIN, right_y)
|
96
125
|
|
97
126
|
# Calculate center based on bar_width and current row
|
98
|
-
label_center = left_y + bars_width / 2
|
127
|
+
label_center = left_y + (bars_width / 2.0)
|
99
128
|
|
100
129
|
# Subtract half a bar width to center left if requested
|
101
130
|
draw_label(label_center, point_index)
|
102
131
|
if @show_labels_for_bar_values
|
103
132
|
bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
|
104
|
-
bar_value_label.prepare_rendering(@label_formatting,
|
105
|
-
draw_value_label(x, y, text)
|
133
|
+
bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
|
134
|
+
draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
|
106
135
|
end
|
107
136
|
end
|
108
137
|
end
|
@@ -118,17 +147,17 @@ private
|
|
118
147
|
number_of_lines = 1 if number_of_lines == 0
|
119
148
|
|
120
149
|
# TODO: Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
|
121
|
-
increment = significant(@spread
|
150
|
+
increment = significant(@spread / number_of_lines)
|
122
151
|
(0..number_of_lines).each do |index|
|
123
152
|
line_diff = (@graph_right - @graph_left) / number_of_lines
|
124
153
|
x = @graph_right - (line_diff * index) - 1
|
125
154
|
|
126
|
-
|
127
|
-
|
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
|
128
157
|
|
129
158
|
unless @hide_line_numbers
|
130
159
|
diff = index - number_of_lines
|
131
|
-
marker_label = BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s) + BigDecimal(minimum_value.to_s)
|
160
|
+
marker_label = (BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s)) + BigDecimal(minimum_value.to_s)
|
132
161
|
label = x_axis_label(marker_label, @increment)
|
133
162
|
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
|
134
163
|
text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + LABEL_MARGIN, Magick::CenterGravity)
|
@@ -39,6 +39,11 @@ class Gruff::SideStackedBar < Gruff::SideBar
|
|
39
39
|
# Prevent drawing of column labels left of a side stacked bar graph. Default is +false+.
|
40
40
|
attr_writer :hide_labels
|
41
41
|
|
42
|
+
def initialize(*)
|
43
|
+
super
|
44
|
+
@has_left_labels = true
|
45
|
+
end
|
46
|
+
|
42
47
|
private
|
43
48
|
|
44
49
|
def initialize_attributes
|
@@ -48,7 +53,7 @@ private
|
|
48
53
|
@label_formatting = nil
|
49
54
|
@show_labels_for_bar_values = false
|
50
55
|
@hide_labels = false
|
51
|
-
@
|
56
|
+
@minimum_value = 0.0
|
52
57
|
end
|
53
58
|
|
54
59
|
def setup_data
|
@@ -56,48 +61,35 @@ private
|
|
56
61
|
super
|
57
62
|
end
|
58
63
|
|
59
|
-
def hide_labels?
|
60
|
-
@hide_labels
|
61
|
-
end
|
62
|
-
|
63
|
-
def hide_left_label_area?
|
64
|
-
hide_labels?
|
65
|
-
end
|
66
|
-
|
67
|
-
def hide_bottom_label_area?
|
68
|
-
@hide_line_markers
|
69
|
-
end
|
70
|
-
|
71
64
|
def draw_graph
|
72
65
|
# Setup spacing.
|
73
66
|
#
|
74
67
|
# Columns sit stacked.
|
75
|
-
bar_width = @graph_height / column_count
|
68
|
+
bar_width = @graph_height / column_count
|
76
69
|
height = Array.new(column_count, 0)
|
77
70
|
length = Array.new(column_count, @graph_left)
|
78
71
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
79
|
-
|
72
|
+
stack_bar_value_labels = Gruff::BarValueLabel::StackedBar.new
|
80
73
|
|
81
74
|
store.norm_data.each_with_index do |data_row, row_index|
|
82
75
|
data_row.points.each_with_index do |data_point, point_index|
|
83
76
|
## using the original calculations from the stacked bar chart to get the difference between
|
84
77
|
## part of the bart chart we wish to stack.
|
85
|
-
temp1 = @graph_left + (@graph_width -
|
86
|
-
|
87
|
-
height[point_index]) + 1
|
88
|
-
temp2 = @graph_left + @graph_width - height[point_index] - 1
|
78
|
+
temp1 = @graph_left + (@graph_width - (data_point * @graph_width) - height[point_index])
|
79
|
+
temp2 = @graph_left + @graph_width - height[point_index]
|
89
80
|
difference = temp2 - temp1
|
90
|
-
difference = 0 if
|
81
|
+
difference = 0 if difference < 0
|
91
82
|
|
92
83
|
left_x = length[point_index]
|
93
84
|
left_y = @graph_top + (bar_width * point_index) + padding
|
94
|
-
right_x = left_x + difference
|
95
|
-
|
85
|
+
right_x = left_x + difference
|
86
|
+
right_x -= @segment_spacing if row_index != store.columns - 1
|
87
|
+
right_y = left_y + (bar_width * @bar_spacing)
|
96
88
|
length[point_index] += difference
|
97
|
-
height[point_index] += (data_point * @graph_width
|
89
|
+
height[point_index] += (data_point * @graph_width)
|
98
90
|
|
99
91
|
bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
|
100
|
-
|
92
|
+
stack_bar_value_labels.add(bar_value_label, point_index)
|
101
93
|
|
102
94
|
# if a data point is 0 it can result in weird really thing lines
|
103
95
|
# that shouldn't even be there being drawn on top of the existing
|
@@ -109,14 +101,15 @@ private
|
|
109
101
|
end
|
110
102
|
# we still need to draw the labels
|
111
103
|
# Calculate center based on bar_width and current row
|
112
|
-
label_center = left_y + bar_width / 2
|
104
|
+
label_center = left_y + (bar_width / 2.0)
|
113
105
|
draw_label(label_center, point_index)
|
114
106
|
end
|
115
107
|
end
|
116
108
|
|
117
109
|
if @show_labels_for_bar_values
|
118
|
-
|
119
|
-
|
110
|
+
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
111
|
+
stack_bar_value_labels.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
|
112
|
+
draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
|
120
113
|
end
|
121
114
|
end
|
122
115
|
end
|
data/lib/gruff/spider.rb
CHANGED
@@ -19,6 +19,11 @@ class Gruff::Spider < Gruff::Base
|
|
19
19
|
attr_writer :hide_axes
|
20
20
|
attr_writer :rotation
|
21
21
|
|
22
|
+
def initialize(max_value, target_width = 800)
|
23
|
+
super(target_width)
|
24
|
+
@max_value = max_value
|
25
|
+
end
|
26
|
+
|
22
27
|
def transparent_background=(value)
|
23
28
|
renderer.transparent_background(@columns, @rows) if value
|
24
29
|
end
|
@@ -27,11 +32,6 @@ class Gruff::Spider < Gruff::Base
|
|
27
32
|
@hide_title = @hide_text = value
|
28
33
|
end
|
29
34
|
|
30
|
-
def initialize(max_value, target_width = 800)
|
31
|
-
super(target_width)
|
32
|
-
@max_value = max_value
|
33
|
-
end
|
34
|
-
|
35
35
|
private
|
36
36
|
|
37
37
|
def initialize_attributes
|
@@ -46,6 +46,24 @@ private
|
|
46
46
|
@hide_line_markers.freeze
|
47
47
|
end
|
48
48
|
|
49
|
+
def setup_graph_measurements
|
50
|
+
super
|
51
|
+
|
52
|
+
@graph_left += LABEL_MARGIN
|
53
|
+
@graph_top += LABEL_MARGIN
|
54
|
+
@graph_right -= LABEL_MARGIN
|
55
|
+
@graph_bottom -= LABEL_MARGIN
|
56
|
+
|
57
|
+
@graph_width = @graph_right - @graph_left
|
58
|
+
@graph_height = @graph_bottom - @graph_top
|
59
|
+
end
|
60
|
+
|
61
|
+
def setup_data
|
62
|
+
raise(Gruff::IncorrectNumberOfDatasetsException, 'Requires 3 or more data sets') if store.length < 3
|
63
|
+
|
64
|
+
super
|
65
|
+
end
|
66
|
+
|
49
67
|
def draw_graph
|
50
68
|
# Setup basic positioning
|
51
69
|
radius = @graph_height / 2.0
|
@@ -68,19 +86,34 @@ private
|
|
68
86
|
end
|
69
87
|
|
70
88
|
def draw_label(center_x, center_y, angle, radius, amount)
|
71
|
-
|
72
|
-
|
73
|
-
|
89
|
+
degree = rad2deg(angle)
|
90
|
+
metrics = text_metrics(@marker_font, amount)
|
91
|
+
|
92
|
+
r_offset = LABEL_MARGIN # The distance out from the center of the pie to get point
|
93
|
+
x_offset = center_x # The label points need to be tweaked slightly
|
94
|
+
|
95
|
+
x_offset -= begin
|
96
|
+
case degree
|
97
|
+
when 0..45, 315..360
|
98
|
+
0
|
99
|
+
when 135..225
|
100
|
+
metrics.width
|
101
|
+
else
|
102
|
+
metrics.width / 2
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
y_offset = center_y - (metrics.height / 2.0) # This one doesn't though
|
74
107
|
x = x_offset + ((radius + r_offset) * Math.cos(angle))
|
75
108
|
y = y_offset + ((radius + r_offset) * Math.sin(angle))
|
76
109
|
|
77
|
-
draw_label_at(
|
110
|
+
draw_label_at(metrics.width, metrics.height, x, y, amount, Magick::CenterGravity)
|
78
111
|
end
|
79
112
|
|
80
113
|
def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
|
81
114
|
return if @hide_axes
|
82
115
|
|
83
|
-
current_angle = @rotation
|
116
|
+
current_angle = deg2rad(@rotation)
|
84
117
|
|
85
118
|
store.data.each do |data_row|
|
86
119
|
x_offset = radius * Math.cos(current_angle)
|
@@ -97,11 +130,11 @@ private
|
|
97
130
|
|
98
131
|
def draw_polygon(center_x, center_y, additive_angle, color = nil)
|
99
132
|
points = []
|
100
|
-
current_angle = @rotation
|
133
|
+
current_angle = deg2rad(@rotation)
|
101
134
|
|
102
135
|
store.data.each do |data_row|
|
103
|
-
points << center_x + normalize_points(data_row.points.first) * Math.cos(current_angle)
|
104
|
-
points << center_y + normalize_points(data_row.points.first) * Math.sin(current_angle)
|
136
|
+
points << (center_x + (normalize_points(data_row.points.first) * Math.cos(current_angle)))
|
137
|
+
points << (center_y + (normalize_points(data_row.points.first) * Math.sin(current_angle)))
|
105
138
|
current_angle += additive_angle
|
106
139
|
end
|
107
140
|
|
data/lib/gruff/stacked_area.rb
CHANGED
@@ -20,13 +20,18 @@ class Gruff::StackedArea < Gruff::Base
|
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
+
def initialize_attributes
|
24
|
+
super
|
25
|
+
@minimum_value = 0.0
|
26
|
+
end
|
27
|
+
|
23
28
|
def setup_data
|
24
29
|
calculate_maximum_by_stack
|
25
30
|
super
|
26
31
|
end
|
27
32
|
|
28
33
|
def draw_graph
|
29
|
-
x_increment = @graph_width / (column_count - 1)
|
34
|
+
x_increment = @graph_width / (column_count - 1)
|
30
35
|
|
31
36
|
height = Array.new(column_count, 0)
|
32
37
|
|
@@ -38,7 +43,7 @@ private
|
|
38
43
|
data_row.points.each_with_index do |data_point, index|
|
39
44
|
# Use incremented x and scaled y
|
40
45
|
new_x = @graph_left + (x_increment * index)
|
41
|
-
new_y = @graph_top + (@graph_height - data_point * @graph_height - height[index])
|
46
|
+
new_y = @graph_top + (@graph_height - (data_point * @graph_height) - height[index])
|
42
47
|
|
43
48
|
height[index] += (data_point * @graph_height)
|
44
49
|
|
@@ -50,15 +55,15 @@ private
|
|
50
55
|
|
51
56
|
poly_points = data_points.dup
|
52
57
|
if prev_data_points
|
53
|
-
(prev_data_points.length / 2 - 1).downto(0) do |i|
|
58
|
+
((prev_data_points.length / 2) - 1).downto(0) do |i|
|
54
59
|
poly_points << prev_data_points[2 * i]
|
55
|
-
poly_points << prev_data_points[2 * i + 1]
|
60
|
+
poly_points << prev_data_points[(2 * i) + 1]
|
56
61
|
end
|
57
62
|
else
|
58
63
|
poly_points << @graph_right
|
59
|
-
poly_points << @graph_bottom - 1
|
64
|
+
poly_points << (@graph_bottom - 1)
|
60
65
|
poly_points << @graph_left
|
61
|
-
poly_points << @graph_bottom - 1
|
66
|
+
poly_points << (@graph_bottom - 1)
|
62
67
|
end
|
63
68
|
poly_points << data_points[0]
|
64
69
|
poly_points << data_points[1]
|