gruff 0.11.0-java → 0.14.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 +66 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +24 -8
- data/.rubocop_todo.yml +57 -53
- data/CHANGELOG.md +34 -0
- data/README.md +15 -7
- data/assets/fonts/LICENSE.txt +202 -0
- data/assets/fonts/Roboto-Bold.ttf +0 -0
- data/assets/fonts/Roboto-Regular.ttf +0 -0
- data/gruff.gemspec +8 -5
- data/lib/gruff.rb +9 -3
- data/lib/gruff/accumulator_bar.rb +3 -3
- data/lib/gruff/area.rb +5 -12
- data/lib/gruff/bar.rb +43 -47
- data/lib/gruff/base.rb +267 -146
- data/lib/gruff/bezier.rb +4 -10
- data/lib/gruff/bullet.rb +13 -19
- data/lib/gruff/dot.rb +14 -19
- data/lib/gruff/font.rb +39 -0
- data/lib/gruff/helper/bar_conversion.rb +28 -13
- data/lib/gruff/helper/bar_value_label.rb +68 -0
- data/lib/gruff/helper/stacked_mixin.rb +1 -2
- data/lib/gruff/histogram.rb +9 -8
- data/lib/gruff/line.rb +59 -56
- data/lib/gruff/mini/bar.rb +10 -7
- data/lib/gruff/mini/legend.rb +19 -10
- data/lib/gruff/mini/pie.rb +10 -8
- data/lib/gruff/mini/side_bar.rb +10 -8
- data/lib/gruff/net.rb +13 -20
- data/lib/gruff/patch/rmagick.rb +22 -24
- data/lib/gruff/patch/string.rb +7 -4
- data/lib/gruff/pie.rb +24 -70
- data/lib/gruff/renderer/bezier.rb +11 -11
- data/lib/gruff/renderer/circle.rb +11 -11
- data/lib/gruff/renderer/dash_line.rb +12 -12
- data/lib/gruff/renderer/dot.rb +16 -16
- data/lib/gruff/renderer/ellipse.rb +11 -11
- data/lib/gruff/renderer/line.rb +12 -12
- data/lib/gruff/renderer/polygon.rb +13 -13
- data/lib/gruff/renderer/polyline.rb +11 -11
- data/lib/gruff/renderer/rectangle.rb +9 -9
- data/lib/gruff/renderer/renderer.rb +23 -50
- data/lib/gruff/renderer/text.rb +32 -29
- data/lib/gruff/scatter.rb +52 -76
- data/lib/gruff/scene.rb +15 -14
- data/lib/gruff/side_bar.rb +49 -52
- data/lib/gruff/side_stacked_bar.rb +29 -20
- data/lib/gruff/spider.rb +13 -22
- data/lib/gruff/stacked_area.rb +10 -16
- data/lib/gruff/stacked_bar.rb +29 -18
- data/lib/gruff/store/{base_data.rb → basic_data.rb} +5 -7
- data/lib/gruff/store/custom_data.rb +4 -6
- data/lib/gruff/store/store.rb +9 -12
- data/lib/gruff/store/xy_data.rb +6 -7
- data/lib/gruff/themes.rb +6 -6
- data/lib/gruff/version.rb +1 -1
- data/rails_generators/gruff/templates/controller.rb +1 -1
- metadata +24 -14
- data/.travis.yml +0 -26
- data/Rakefile +0 -47
- data/assets/plastik/blue.png +0 -0
- data/assets/plastik/green.png +0 -0
- data/assets/plastik/red.png +0 -0
- data/docker/Dockerfile +0 -14
- data/docker/build.sh +0 -4
- data/docker/launch.sh +0 -4
- data/lib/gruff/helper/bar_value_label_mixin.rb +0 -30
- data/lib/gruff/photo_bar.rb +0 -97
data/lib/gruff/scatter.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'gruff/base'
|
|
4
|
-
|
|
5
3
|
#
|
|
6
4
|
# Here's how to set up a Gruff::Scatter.
|
|
7
5
|
#
|
|
@@ -30,62 +28,18 @@ class Gruff::Scatter < Gruff::Base
|
|
|
30
28
|
# This is useful when working with a small range of high values (for example, a date range of months, while seconds as units).
|
|
31
29
|
attr_writer :disable_significant_rounding_x_axis
|
|
32
30
|
|
|
33
|
-
# Allow
|
|
34
|
-
attr_writer :
|
|
31
|
+
# Allow for vertical marker lines.
|
|
32
|
+
attr_writer :show_vertical_markers
|
|
35
33
|
|
|
36
34
|
# Allow using vertical labels in the X axis (and setting the label margin).
|
|
37
35
|
attr_writer :x_label_margin
|
|
38
36
|
attr_writer :use_vertical_x_labels
|
|
39
37
|
|
|
40
|
-
# Allow
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@store = Gruff::Store.new(Gruff::Store::XYData)
|
|
46
|
-
end
|
|
47
|
-
private :initialize_store
|
|
48
|
-
|
|
49
|
-
def initialize_ivars
|
|
50
|
-
super
|
|
51
|
-
|
|
52
|
-
@baseline_x_color = @baseline_y_color = 'red'
|
|
53
|
-
@baseline_x_value = @baseline_y_value = nil
|
|
54
|
-
@circle_radius = nil
|
|
55
|
-
@disable_significant_rounding_x_axis = false
|
|
56
|
-
@enable_vertical_line_markers = false
|
|
57
|
-
@marker_x_count = nil
|
|
58
|
-
@maximum_x_value = @minimum_x_value = nil
|
|
59
|
-
@stroke_width = nil
|
|
60
|
-
@use_vertical_x_labels = false
|
|
61
|
-
@x_axis_label_format = nil
|
|
62
|
-
@x_label_margin = nil
|
|
63
|
-
@y_axis_label_format = nil
|
|
64
|
-
end
|
|
65
|
-
private :initialize_ivars
|
|
66
|
-
|
|
67
|
-
def draw
|
|
68
|
-
super
|
|
69
|
-
return unless data_given?
|
|
70
|
-
|
|
71
|
-
# Check to see if more than one datapoint was given. NaN can result otherwise.
|
|
72
|
-
@x_increment = (@x_spread > 1) ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
|
|
73
|
-
|
|
74
|
-
store.norm_data.each do |data_row|
|
|
75
|
-
data_row.coordinates.each do |x_value, y_value|
|
|
76
|
-
next if y_value.nil? || x_value.nil?
|
|
77
|
-
|
|
78
|
-
new_x = get_x_coord(x_value, @graph_width, @graph_left)
|
|
79
|
-
new_y = @graph_top + (@graph_height - y_value * @graph_height)
|
|
80
|
-
|
|
81
|
-
# Reset each time to avoid thin-line errors
|
|
82
|
-
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
|
83
|
-
circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
|
|
84
|
-
Gruff::Renderer::Circle.new(color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
Gruff::Renderer.finish
|
|
38
|
+
# Allow enabling vertical lines. When you have a lot of data, they can work great.
|
|
39
|
+
# @deprecated Please use +show_vertical_markers+ attribute instead.
|
|
40
|
+
def enable_vertical_line_markers=(value)
|
|
41
|
+
warn '#enable_vertical_line_markers= is deprecated. Please use `show_vertical_markers` attribute instead'
|
|
42
|
+
@show_vertical_markers = value
|
|
89
43
|
end
|
|
90
44
|
|
|
91
45
|
# The first parameter is the name of the dataset. The next two are the
|
|
@@ -141,6 +95,44 @@ class Gruff::Scatter < Gruff::Base
|
|
|
141
95
|
|
|
142
96
|
private
|
|
143
97
|
|
|
98
|
+
def initialize_store
|
|
99
|
+
@store = Gruff::Store.new(Gruff::Store::XYData)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def initialize_attributes
|
|
103
|
+
super
|
|
104
|
+
|
|
105
|
+
@baseline_x_color = @baseline_y_color = 'red'
|
|
106
|
+
@baseline_x_value = @baseline_y_value = nil
|
|
107
|
+
@circle_radius = nil
|
|
108
|
+
@disable_significant_rounding_x_axis = false
|
|
109
|
+
@show_vertical_markers = false
|
|
110
|
+
@marker_x_count = nil
|
|
111
|
+
@maximum_x_value = @minimum_x_value = nil
|
|
112
|
+
@stroke_width = nil
|
|
113
|
+
@use_vertical_x_labels = false
|
|
114
|
+
@x_label_margin = nil
|
|
115
|
+
end
|
|
116
|
+
|
|
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
|
+
store.norm_data.each do |data_row|
|
|
122
|
+
data_row.coordinates.each do |x_value, y_value|
|
|
123
|
+
next if y_value.nil? || x_value.nil?
|
|
124
|
+
|
|
125
|
+
new_x = get_x_coord(x_value, @graph_width, @graph_left)
|
|
126
|
+
new_y = @graph_top + (@graph_height - y_value * @graph_height)
|
|
127
|
+
|
|
128
|
+
# Reset each time to avoid thin-line errors
|
|
129
|
+
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
|
130
|
+
circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
|
|
131
|
+
Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
144
136
|
def setup_data
|
|
145
137
|
# Update the global min/max values for the x data
|
|
146
138
|
@maximum_x_value ||= store.max_x
|
|
@@ -190,12 +182,12 @@ private
|
|
|
190
182
|
end
|
|
191
183
|
else
|
|
192
184
|
# TODO: Make this work for negative values
|
|
193
|
-
@maximum_x_value = [
|
|
185
|
+
@maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment].max
|
|
194
186
|
@minimum_x_value = @minimum_x_value.floor
|
|
195
187
|
calculate_spread
|
|
196
188
|
normalize
|
|
197
189
|
|
|
198
|
-
@
|
|
190
|
+
@marker_x_count = (@x_spread / @x_axis_increment).to_i
|
|
199
191
|
@x_increment = @x_axis_increment
|
|
200
192
|
end
|
|
201
193
|
increment_x_scaled = @graph_width.to_f / (@x_spread / @x_increment)
|
|
@@ -203,42 +195,26 @@ private
|
|
|
203
195
|
# Draw vertical line markers and annotate with numbers
|
|
204
196
|
(0..@marker_x_count).each do |index|
|
|
205
197
|
# TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
|
|
206
|
-
if @
|
|
198
|
+
if @show_vertical_markers
|
|
207
199
|
x = @graph_left + @graph_width - index.to_f * increment_x_scaled
|
|
208
200
|
|
|
209
|
-
line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
|
|
201
|
+
line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
|
|
210
202
|
line_renderer.render(x, @graph_top, x, @graph_bottom)
|
|
211
203
|
end
|
|
212
204
|
|
|
213
205
|
unless @hide_line_numbers
|
|
214
|
-
marker_label = index * @x_increment + @minimum_x_value.
|
|
206
|
+
marker_label = BigDecimal(index.to_s) * BigDecimal(@x_increment.to_s) + BigDecimal(@minimum_x_value.to_s)
|
|
215
207
|
y_offset = @graph_bottom + (@x_label_margin || LABEL_MARGIN)
|
|
216
208
|
x_offset = get_x_coord(index.to_f, increment_x_scaled, @graph_left)
|
|
217
209
|
|
|
218
|
-
label =
|
|
210
|
+
label = x_axis_label(marker_label, @x_increment)
|
|
219
211
|
rotation = -90.0 if @use_vertical_x_labels
|
|
220
|
-
text_renderer = Gruff::Renderer::Text.new(label, font: @
|
|
212
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font, rotation: rotation)
|
|
221
213
|
text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
|
|
222
214
|
end
|
|
223
215
|
end
|
|
224
216
|
end
|
|
225
217
|
|
|
226
|
-
def label(value, increment)
|
|
227
|
-
if @y_axis_label_format
|
|
228
|
-
@y_axis_label_format.call(value)
|
|
229
|
-
else
|
|
230
|
-
super
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def vertical_label(value, increment)
|
|
235
|
-
if @x_axis_label_format
|
|
236
|
-
@x_axis_label_format.call(value)
|
|
237
|
-
else
|
|
238
|
-
label(value, increment)
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
218
|
def get_x_coord(x_data_point, width, offset) #:nodoc:
|
|
243
219
|
x_data_point * width + offset
|
|
244
220
|
end
|
data/lib/gruff/scene.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'observer'
|
|
4
|
-
require 'gruff/base'
|
|
5
4
|
|
|
6
5
|
# A scene is a non-linear graph that assembles layers together to tell a story.
|
|
7
6
|
# Layers are folders with appropriately named files (see below). You can group
|
|
@@ -53,7 +52,7 @@ class Gruff::Scene < Gruff::Base
|
|
|
53
52
|
# Join all the custom paths and filter out the empty ones
|
|
54
53
|
image_paths = @layers.map(&:path).reject(&:empty?)
|
|
55
54
|
images = Magick::ImageList.new(*image_paths)
|
|
56
|
-
|
|
55
|
+
renderer.background_image = images.flatten_images
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
def layers=(ordered_list)
|
|
@@ -133,18 +132,20 @@ class Gruff::Layer
|
|
|
133
132
|
|
|
134
133
|
# Choose the appropriate filename for this layer, based on the input
|
|
135
134
|
def update(value)
|
|
136
|
-
@selected_filename =
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
135
|
+
@selected_filename = begin
|
|
136
|
+
case value.to_s
|
|
137
|
+
when /^(true|false)$/
|
|
138
|
+
select_boolean value
|
|
139
|
+
when /^(\w|\s)+$/
|
|
140
|
+
select_string value
|
|
141
|
+
when /^-?(\d+\.)?\d+$/
|
|
142
|
+
select_numeric value
|
|
143
|
+
when /(\d\d):(\d\d):\d\d/
|
|
144
|
+
select_time "#{Regexp.last_match(1)}#{Regexp.last_match(2)}"
|
|
145
|
+
else
|
|
146
|
+
select_default
|
|
147
|
+
end
|
|
148
|
+
end
|
|
148
149
|
# Finally, try to use 'default' if we're still blank
|
|
149
150
|
@selected_filename ||= select_default
|
|
150
151
|
end
|
data/lib/gruff/side_bar.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'gruff/base'
|
|
4
|
-
|
|
5
3
|
# Graph with individual horizontal bars instead of vertical bars.
|
|
6
4
|
#
|
|
7
5
|
# Here's how to set up a Gruff::SideBar.
|
|
@@ -27,7 +25,7 @@ class Gruff::SideBar < Gruff::Base
|
|
|
27
25
|
# Spacing factor applied between a group of bars belonging to the same label.
|
|
28
26
|
attr_writer :group_spacing
|
|
29
27
|
|
|
30
|
-
# Set the number output format
|
|
28
|
+
# Set the number output format string or lambda.
|
|
31
29
|
# Default is +"%.2f"+.
|
|
32
30
|
attr_writer :label_formatting
|
|
33
31
|
|
|
@@ -35,78 +33,80 @@ class Gruff::SideBar < Gruff::Base
|
|
|
35
33
|
# Default is +false+.
|
|
36
34
|
attr_writer :show_labels_for_bar_values
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
# Prevent drawing of column labels left of a side bar graph. Default is +false+.
|
|
37
|
+
attr_writer :hide_labels
|
|
38
|
+
|
|
39
|
+
# With Side Bars use the data label for the marker value to the left of the bar.
|
|
40
|
+
# @deprecated
|
|
41
|
+
def use_data_label=(_value)
|
|
42
|
+
warn '#use_data_label is deprecated. It is no longer effective.'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def initialize_attributes
|
|
39
48
|
super
|
|
40
49
|
@bar_spacing = 0.9
|
|
41
50
|
@group_spacing = 10
|
|
42
51
|
@label_formatting = nil
|
|
43
52
|
@show_labels_for_bar_values = false
|
|
53
|
+
@hide_labels = false
|
|
54
|
+
@has_left_labels = true
|
|
44
55
|
end
|
|
45
|
-
private :initialize_ivars
|
|
46
56
|
|
|
47
|
-
def
|
|
48
|
-
@
|
|
49
|
-
|
|
57
|
+
def hide_labels?
|
|
58
|
+
@hide_labels
|
|
59
|
+
end
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
def hide_left_label_area?
|
|
62
|
+
hide_labels?
|
|
63
|
+
end
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
def hide_bottom_label_area?
|
|
66
|
+
@hide_line_markers
|
|
54
67
|
end
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
# Value to avoid completely overwriting the coordinate axis
|
|
70
|
+
AXIS_MARGIN = 0.5
|
|
57
71
|
|
|
58
|
-
def
|
|
72
|
+
def draw_graph
|
|
59
73
|
# Setup spacing.
|
|
60
74
|
#
|
|
61
75
|
bars_width = (@graph_height - calculate_spacing) / column_count.to_f
|
|
62
76
|
bar_width = bars_width / store.length
|
|
63
|
-
height = Array.new(column_count, 0)
|
|
64
|
-
length = Array.new(column_count, @graph_left)
|
|
65
77
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
|
66
78
|
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
# Setup the BarConversion Object
|
|
80
|
+
conversion = Gruff::BarConversion.new(
|
|
81
|
+
top: @graph_right, bottom: @graph_left,
|
|
82
|
+
minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
|
|
83
|
+
)
|
|
71
84
|
|
|
72
85
|
store.norm_data.each_with_index do |data_row, row_index|
|
|
73
86
|
data_row.points.each_with_index do |data_point, point_index|
|
|
74
87
|
group_spacing = @group_spacing * @scale * point_index
|
|
75
88
|
|
|
76
|
-
# Using the original calcs from the stacked bar chart
|
|
77
|
-
# to get the difference between
|
|
78
|
-
# part of the bart chart we wish to stack.
|
|
79
|
-
temp1 = @graph_left + (@graph_width - data_point * @graph_width - height[point_index])
|
|
80
|
-
temp2 = @graph_left + @graph_width - height[point_index]
|
|
81
|
-
difference = temp2 - temp1
|
|
82
|
-
|
|
83
|
-
left_x = length[point_index] - 1
|
|
84
89
|
left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
|
|
85
|
-
right_x = left_x + difference
|
|
86
90
|
right_y = left_y + bar_width * @bar_spacing
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
left_x, right_x = conversion.get_top_bottom_scaled(data_point).sort
|
|
89
93
|
|
|
90
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: data_row.color)
|
|
91
|
-
rect_renderer.render(left_x, left_y, right_x, right_y)
|
|
94
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
|
|
95
|
+
rect_renderer.render(left_x + AXIS_MARGIN, left_y, right_x + AXIS_MARGIN, right_y)
|
|
92
96
|
|
|
93
97
|
# Calculate center based on bar_width and current row
|
|
98
|
+
label_center = left_y + bars_width / 2
|
|
94
99
|
|
|
95
|
-
if
|
|
96
|
-
|
|
97
|
-
draw_label(label_center, row_index, store.norm_data[row_index].label)
|
|
98
|
-
else
|
|
99
|
-
label_center = left_y + bars_width / 2
|
|
100
|
-
draw_label(label_center, point_index)
|
|
101
|
-
end
|
|
100
|
+
# Subtract half a bar width to center left if requested
|
|
101
|
+
draw_label(label_center, point_index)
|
|
102
102
|
if @show_labels_for_bar_values
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
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, bar_width) do |x, y, text|
|
|
105
|
+
draw_value_label(x, y, text)
|
|
106
|
+
end
|
|
105
107
|
end
|
|
106
108
|
end
|
|
107
109
|
end
|
|
108
|
-
|
|
109
|
-
Gruff::Renderer.finish
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
# Instead of base class version, draws vertical background lines and label
|
|
@@ -114,7 +114,7 @@ private
|
|
|
114
114
|
return if @hide_line_markers
|
|
115
115
|
|
|
116
116
|
# Draw horizontal line markers and annotate with numbers
|
|
117
|
-
number_of_lines =
|
|
117
|
+
number_of_lines = marker_count
|
|
118
118
|
number_of_lines = 1 if number_of_lines == 0
|
|
119
119
|
|
|
120
120
|
# TODO: Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
|
|
@@ -123,14 +123,14 @@ private
|
|
|
123
123
|
line_diff = (@graph_right - @graph_left) / number_of_lines
|
|
124
124
|
x = @graph_right - (line_diff * index) - 1
|
|
125
125
|
|
|
126
|
-
line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
|
|
126
|
+
line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
|
|
127
127
|
line_renderer.render(x, @graph_bottom, x, @graph_top)
|
|
128
128
|
|
|
129
|
-
diff = index - number_of_lines
|
|
130
|
-
marker_label = diff.abs * increment + minimum_value
|
|
131
|
-
|
|
132
129
|
unless @hide_line_numbers
|
|
133
|
-
|
|
130
|
+
diff = index - number_of_lines
|
|
131
|
+
marker_label = BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s) + BigDecimal(minimum_value.to_s)
|
|
132
|
+
label = x_axis_label(marker_label, @increment)
|
|
133
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
|
|
134
134
|
text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + LABEL_MARGIN, Magick::CenterGravity)
|
|
135
135
|
end
|
|
136
136
|
end
|
|
@@ -139,12 +139,9 @@ private
|
|
|
139
139
|
##
|
|
140
140
|
# Draw on the Y axis instead of the X
|
|
141
141
|
|
|
142
|
-
def draw_label(y_offset, index
|
|
142
|
+
def draw_label(y_offset, index)
|
|
143
143
|
draw_unique_label(index) do
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
text_renderer = Gruff::Renderer::Text.new(lbl, font: @font, size: @marker_font_size, color: @font_color)
|
|
147
|
-
text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, Magick::EastGravity)
|
|
144
|
+
draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
|
|
148
145
|
end
|
|
149
146
|
end
|
|
150
147
|
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'gruff/side_bar'
|
|
4
|
-
require 'gruff/helper/stacked_mixin'
|
|
5
|
-
|
|
6
3
|
#
|
|
7
4
|
# New gruff graph type added to enable sideways stacking bar charts
|
|
8
5
|
# (basically looks like a x/y flip of a standard stacking bar chart)
|
|
@@ -24,7 +21,6 @@ require 'gruff/helper/stacked_mixin'
|
|
|
24
21
|
#
|
|
25
22
|
class Gruff::SideStackedBar < Gruff::SideBar
|
|
26
23
|
include StackedMixin
|
|
27
|
-
include BarValueLabelMixin
|
|
28
24
|
|
|
29
25
|
# Spacing factor applied between bars.
|
|
30
26
|
attr_writer :bar_spacing
|
|
@@ -32,7 +28,7 @@ class Gruff::SideStackedBar < Gruff::SideBar
|
|
|
32
28
|
# Number of pixels between bar segments.
|
|
33
29
|
attr_writer :segment_spacing
|
|
34
30
|
|
|
35
|
-
# Set the number output format
|
|
31
|
+
# Set the number output format string or lambda.
|
|
36
32
|
# Default is +"%.2f"+.
|
|
37
33
|
attr_writer :label_formatting
|
|
38
34
|
|
|
@@ -40,24 +36,39 @@ class Gruff::SideStackedBar < Gruff::SideBar
|
|
|
40
36
|
# Default is +false+.
|
|
41
37
|
attr_writer :show_labels_for_bar_values
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
# Prevent drawing of column labels left of a side stacked bar graph. Default is +false+.
|
|
40
|
+
attr_writer :hide_labels
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def initialize_attributes
|
|
44
45
|
super
|
|
45
46
|
@bar_spacing = 0.9
|
|
46
47
|
@segment_spacing = 2.0
|
|
47
48
|
@label_formatting = nil
|
|
48
49
|
@show_labels_for_bar_values = false
|
|
50
|
+
@hide_labels = false
|
|
51
|
+
@has_left_labels = true
|
|
49
52
|
end
|
|
50
|
-
private :initialize_ivars
|
|
51
53
|
|
|
52
|
-
def
|
|
53
|
-
@has_left_labels = true
|
|
54
|
+
def setup_data
|
|
54
55
|
calculate_maximum_by_stack
|
|
55
56
|
super
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
def hide_labels?
|
|
60
|
+
@hide_labels
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def hide_left_label_area?
|
|
64
|
+
hide_labels?
|
|
65
|
+
end
|
|
59
66
|
|
|
60
|
-
def
|
|
67
|
+
def hide_bottom_label_area?
|
|
68
|
+
@hide_line_markers
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def draw_graph
|
|
61
72
|
# Setup spacing.
|
|
62
73
|
#
|
|
63
74
|
# Columns sit stacked.
|
|
@@ -65,11 +76,11 @@ private
|
|
|
65
76
|
height = Array.new(column_count, 0)
|
|
66
77
|
length = Array.new(column_count, @graph_left)
|
|
67
78
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
|
68
|
-
|
|
79
|
+
stack_bar_value_label = Gruff::BarValueLabel::StackedBar.new
|
|
69
80
|
|
|
70
81
|
store.norm_data.each_with_index do |data_row, row_index|
|
|
71
82
|
data_row.points.each_with_index do |data_point, point_index|
|
|
72
|
-
## using the original
|
|
83
|
+
## using the original calculations from the stacked bar chart to get the difference between
|
|
73
84
|
## part of the bart chart we wish to stack.
|
|
74
85
|
temp1 = @graph_left + (@graph_width -
|
|
75
86
|
data_point * @graph_width -
|
|
@@ -84,14 +95,14 @@ private
|
|
|
84
95
|
length[point_index] += difference
|
|
85
96
|
height[point_index] += (data_point * @graph_width - 2)
|
|
86
97
|
|
|
87
|
-
bar_value_label
|
|
88
|
-
bar_value_label
|
|
98
|
+
bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
|
|
99
|
+
stack_bar_value_label.add(bar_value_label, point_index)
|
|
89
100
|
|
|
90
101
|
# if a data point is 0 it can result in weird really thing lines
|
|
91
102
|
# that shouldn't even be there being drawn on top of the existing
|
|
92
103
|
# bar - this is bad
|
|
93
104
|
if data_point != 0
|
|
94
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: data_row.color)
|
|
105
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
|
|
95
106
|
rect_renderer.render(left_x, left_y, right_x, right_y)
|
|
96
107
|
# Calculate center based on bar_width and current row
|
|
97
108
|
end
|
|
@@ -103,11 +114,9 @@ private
|
|
|
103
114
|
end
|
|
104
115
|
|
|
105
116
|
if @show_labels_for_bar_values
|
|
106
|
-
|
|
107
|
-
draw_value_label(x, y, text
|
|
117
|
+
stack_bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
|
|
118
|
+
draw_value_label(x, y, text)
|
|
108
119
|
end
|
|
109
120
|
end
|
|
110
|
-
|
|
111
|
-
Gruff::Renderer.finish
|
|
112
121
|
end
|
|
113
122
|
end
|