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/bezier.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'gruff/base'
|
|
4
|
-
|
|
5
3
|
#
|
|
6
4
|
# Gruff::Bezier is a special line graph that have
|
|
7
5
|
# the bezier curve.
|
|
@@ -21,11 +19,9 @@ require 'gruff/base'
|
|
|
21
19
|
# g.write('bezier.png')
|
|
22
20
|
#
|
|
23
21
|
class Gruff::Bezier < Gruff::Base
|
|
24
|
-
|
|
25
|
-
super
|
|
26
|
-
|
|
27
|
-
return unless data_given?
|
|
22
|
+
private
|
|
28
23
|
|
|
24
|
+
def draw_graph
|
|
29
25
|
x_increment = @graph_width / (column_count - 1).to_f
|
|
30
26
|
|
|
31
27
|
store.norm_data.each do |data_row|
|
|
@@ -50,12 +46,10 @@ class Gruff::Bezier < Gruff::Base
|
|
|
50
46
|
stroke_width = clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
|
51
47
|
|
|
52
48
|
if RUBY_PLATFORM == 'java'
|
|
53
|
-
Gruff::Renderer::Polyline.new(color: data_row.color, width: stroke_width).render(poly_points)
|
|
49
|
+
Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
|
|
54
50
|
else
|
|
55
|
-
Gruff::Renderer::Bezier.new(color: data_row.color, width: stroke_width).render(poly_points)
|
|
51
|
+
Gruff::Renderer::Bezier.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
|
|
56
52
|
end
|
|
57
53
|
end
|
|
58
|
-
|
|
59
|
-
Gruff::Renderer.finish
|
|
60
54
|
end
|
|
61
55
|
end
|
data/lib/gruff/bullet.rb
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'gruff/base'
|
|
4
|
-
require 'gruff/themes'
|
|
5
|
-
|
|
6
3
|
#
|
|
7
4
|
# A bullet graph is a variation of a bar graph.
|
|
8
5
|
# http://en.wikipedia.org/wiki/Bullet_graph
|
|
@@ -16,6 +13,8 @@ require 'gruff/themes'
|
|
|
16
13
|
#
|
|
17
14
|
class Gruff::Bullet < Gruff::Base
|
|
18
15
|
def initialize(target_width = '400x40')
|
|
16
|
+
super
|
|
17
|
+
|
|
19
18
|
if target_width.is_a?(String)
|
|
20
19
|
@columns, @rows = target_width.split('x').map(&:to_f)
|
|
21
20
|
else
|
|
@@ -25,19 +24,16 @@ class Gruff::Bullet < Gruff::Base
|
|
|
25
24
|
@columns.freeze
|
|
26
25
|
@rows.freeze
|
|
27
26
|
|
|
28
|
-
initialize_graph_scale
|
|
29
|
-
initialize_ivars
|
|
30
|
-
initialize_store
|
|
31
|
-
|
|
32
27
|
self.theme = Gruff::Themes::GREYSCALE
|
|
33
28
|
end
|
|
34
29
|
|
|
35
|
-
def
|
|
30
|
+
def initialize_attributes
|
|
36
31
|
super
|
|
37
32
|
|
|
38
|
-
@
|
|
33
|
+
@title_font.size = 20
|
|
34
|
+
@title_font.bold = false
|
|
39
35
|
end
|
|
40
|
-
private :
|
|
36
|
+
private :initialize_attributes
|
|
41
37
|
|
|
42
38
|
def data(value, maximum_value, options = {})
|
|
43
39
|
@value = value.to_f
|
|
@@ -56,7 +52,7 @@ class Gruff::Bullet < Gruff::Base
|
|
|
56
52
|
|
|
57
53
|
draw_title
|
|
58
54
|
|
|
59
|
-
title_width = calculate_width(@
|
|
55
|
+
title_width = calculate_width(@title_font, @title)
|
|
60
56
|
margin = 30.0
|
|
61
57
|
thickness = @raw_rows / 6.0
|
|
62
58
|
right_margin = margin
|
|
@@ -65,7 +61,7 @@ class Gruff::Bullet < Gruff::Base
|
|
|
65
61
|
graph_height = thickness * 3.0
|
|
66
62
|
|
|
67
63
|
# Background
|
|
68
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: @colors[0])
|
|
64
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @colors[0])
|
|
69
65
|
rect_renderer.render(graph_left, 0, graph_left + graph_width, graph_height)
|
|
70
66
|
|
|
71
67
|
[:high, :low].each_with_index do |indicator, index|
|
|
@@ -73,7 +69,7 @@ class Gruff::Bullet < Gruff::Base
|
|
|
73
69
|
|
|
74
70
|
indicator_width_x = graph_left + graph_width * (@options[indicator] / maximum_value)
|
|
75
71
|
|
|
76
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: @colors[index + 1])
|
|
72
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @colors[index + 1])
|
|
77
73
|
rect_renderer.render(graph_left, 0, indicator_width_x, graph_height)
|
|
78
74
|
end
|
|
79
75
|
|
|
@@ -81,15 +77,13 @@ class Gruff::Bullet < Gruff::Base
|
|
|
81
77
|
target_x = graph_left + graph_width * (@options[:target] / maximum_value)
|
|
82
78
|
half_thickness = thickness / 2.0
|
|
83
79
|
|
|
84
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: @
|
|
80
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @marker_color)
|
|
85
81
|
rect_renderer.render(target_x, half_thickness, target_x + half_thickness, thickness * 2 + half_thickness)
|
|
86
82
|
end
|
|
87
83
|
|
|
88
84
|
# Value
|
|
89
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: @
|
|
85
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: @marker_color)
|
|
90
86
|
rect_renderer.render(graph_left, thickness, graph_left + graph_width * (@value / maximum_value), thickness * 2)
|
|
91
|
-
|
|
92
|
-
Gruff::Renderer.finish
|
|
93
87
|
end
|
|
94
88
|
|
|
95
89
|
private
|
|
@@ -97,9 +91,9 @@ private
|
|
|
97
91
|
def draw_title
|
|
98
92
|
return if hide_title?
|
|
99
93
|
|
|
100
|
-
font_height = calculate_caps_height(
|
|
94
|
+
font_height = calculate_caps_height(@title_font)
|
|
101
95
|
|
|
102
|
-
text_renderer = Gruff::Renderer::Text.new(@title, font: @
|
|
96
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, @title, font: @title_font)
|
|
103
97
|
text_renderer.add_to_render_queue(1.0, 1.0, font_height / 2, font_height / 2, Magick::NorthWestGravity)
|
|
104
98
|
end
|
|
105
99
|
end
|
data/lib/gruff/dot.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'gruff/base'
|
|
4
|
-
|
|
5
3
|
#
|
|
6
4
|
# Graph with dots and labels along a vertical access.
|
|
7
5
|
# see: 'Creating More Effective Graphs' by Robbins
|
|
@@ -16,12 +14,14 @@ require 'gruff/base'
|
|
|
16
14
|
# g.write('dot.png')
|
|
17
15
|
#
|
|
18
16
|
class Gruff::Dot < Gruff::Base
|
|
19
|
-
|
|
20
|
-
@has_left_labels = true
|
|
21
|
-
super
|
|
17
|
+
private
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
def initialize_attributes
|
|
20
|
+
super
|
|
21
|
+
@has_left_labels = true
|
|
22
|
+
end
|
|
24
23
|
|
|
24
|
+
def draw_graph
|
|
25
25
|
# Setup spacing.
|
|
26
26
|
#
|
|
27
27
|
spacing_factor = 1.0
|
|
@@ -36,34 +36,30 @@ class Gruff::Dot < Gruff::Base
|
|
|
36
36
|
y_pos = @graph_top + (items_width * point_index) + padding + (items_width.to_f / 2.0).round
|
|
37
37
|
|
|
38
38
|
if row_index == 0
|
|
39
|
-
Gruff::Renderer::Line.new(color: @marker_color).render(@graph_left, y_pos, @graph_left + @graph_width, y_pos)
|
|
39
|
+
Gruff::Renderer::Line.new(renderer, color: @marker_color).render(@graph_left, y_pos, @graph_left + @graph_width, y_pos)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
Gruff::Renderer::Circle.new(color: data_row.color).render(x_pos, y_pos, x_pos + (item_width.to_f / 3.0).round, y_pos)
|
|
42
|
+
Gruff::Renderer::Circle.new(renderer, color: data_row.color).render(x_pos, y_pos, x_pos + (item_width.to_f / 3.0).round, y_pos)
|
|
43
43
|
|
|
44
44
|
draw_label(y_pos, point_index)
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
|
-
|
|
48
|
-
Gruff::Renderer.finish
|
|
49
47
|
end
|
|
50
48
|
|
|
51
|
-
protected
|
|
52
|
-
|
|
53
49
|
# Instead of base class version, draws vertical background lines and label
|
|
54
50
|
def draw_line_markers
|
|
55
51
|
return if @hide_line_markers
|
|
56
52
|
|
|
57
|
-
(0
|
|
58
|
-
marker_label =
|
|
53
|
+
(0..marker_count).each do |index|
|
|
54
|
+
marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
|
|
59
55
|
x = @graph_left + (marker_label - minimum_value) * @graph_width / @spread
|
|
60
56
|
|
|
61
|
-
line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
|
|
57
|
+
line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
|
|
62
58
|
line_renderer.render(x, @graph_bottom, x, @graph_bottom + 5)
|
|
63
59
|
|
|
64
60
|
unless @hide_line_numbers
|
|
65
|
-
label =
|
|
66
|
-
text_renderer = Gruff::Renderer::Text.new(label, font: @
|
|
61
|
+
label = y_axis_label(marker_label, @increment)
|
|
62
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
|
|
67
63
|
text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + (LABEL_MARGIN * 1.5), Magick::CenterGravity)
|
|
68
64
|
end
|
|
69
65
|
end
|
|
@@ -74,8 +70,7 @@ protected
|
|
|
74
70
|
|
|
75
71
|
def draw_label(y_offset, index)
|
|
76
72
|
draw_unique_label(index) do
|
|
77
|
-
|
|
78
|
-
text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, Magick::EastGravity)
|
|
73
|
+
draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
|
|
79
74
|
end
|
|
80
75
|
end
|
|
81
76
|
end
|
data/lib/gruff/font.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Handle font setting to draw texts
|
|
4
|
+
class Gruff::Font
|
|
5
|
+
BOLD_PATH = File.expand_path(File.join(__FILE__, '../../../assets/fonts/Roboto-Bold.ttf')).freeze
|
|
6
|
+
REGULAR_PATH = File.expand_path(File.join(__FILE__, '../../../assets/fonts/Roboto-Regular.ttf')).freeze
|
|
7
|
+
|
|
8
|
+
# Get/set font path.
|
|
9
|
+
attr_accessor :path
|
|
10
|
+
|
|
11
|
+
# Get/set font size.
|
|
12
|
+
attr_accessor :size
|
|
13
|
+
|
|
14
|
+
# Get/set font setting whether render bold text.
|
|
15
|
+
attr_accessor :bold
|
|
16
|
+
|
|
17
|
+
# Get/set font color.
|
|
18
|
+
attr_accessor :color
|
|
19
|
+
|
|
20
|
+
def initialize(path: nil, size: 20.0, bold: false, color: 'white')
|
|
21
|
+
@path = path
|
|
22
|
+
@bold = bold
|
|
23
|
+
@size = size
|
|
24
|
+
@color = color
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get font weight.
|
|
28
|
+
# @return [Magick::WeightType] font weight
|
|
29
|
+
def weight
|
|
30
|
+
@bold ? Magick::BoldWeight : Magick::NormalWeight
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @private
|
|
34
|
+
def file_path
|
|
35
|
+
return @path if @path
|
|
36
|
+
|
|
37
|
+
@bold ? BOLD_PATH : REGULAR_PATH
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
##
|
|
4
4
|
# Original Author: David Stokar
|
|
5
5
|
#
|
|
6
|
-
# This class
|
|
6
|
+
# This class performs the y coordinates conversion for the bar class.
|
|
7
7
|
#
|
|
8
8
|
# There are three cases:
|
|
9
9
|
#
|
|
@@ -14,29 +14,44 @@
|
|
|
14
14
|
# @private
|
|
15
15
|
class Gruff::BarConversion
|
|
16
16
|
attr_writer :mode
|
|
17
|
-
attr_writer :zero
|
|
18
|
-
attr_writer :graph_top
|
|
19
|
-
attr_writer :graph_height
|
|
20
|
-
attr_writer :minimum_value
|
|
21
|
-
attr_writer :spread
|
|
22
17
|
|
|
23
|
-
def
|
|
18
|
+
def initialize(top:, bottom:, minimum_value:, maximum_value:, spread:)
|
|
19
|
+
@graph_top = top
|
|
20
|
+
@graph_height = bottom - top
|
|
21
|
+
@spread = spread
|
|
22
|
+
@minimum_value = minimum_value
|
|
23
|
+
@maximum_value = maximum_value
|
|
24
|
+
|
|
25
|
+
if minimum_value >= 0
|
|
26
|
+
# all bars go from zero to positive
|
|
27
|
+
@mode = 1
|
|
28
|
+
elsif maximum_value <= 0
|
|
29
|
+
# all bars go from 0 to negative
|
|
30
|
+
@mode = 2
|
|
31
|
+
else
|
|
32
|
+
# bars either go from zero to negative or to positive
|
|
33
|
+
@mode = 3
|
|
34
|
+
@zero = -minimum_value / @spread
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def get_top_bottom_scaled(data_point)
|
|
24
39
|
result = []
|
|
25
40
|
|
|
26
41
|
case @mode
|
|
27
42
|
when 1
|
|
28
43
|
# minimum value >= 0 ( only positive values )
|
|
29
|
-
result[0] = @graph_top + @graph_height * (1 - data_point)
|
|
30
|
-
result[1] = @graph_top + @graph_height
|
|
44
|
+
result[0] = @graph_top + @graph_height * (1 - data_point)
|
|
45
|
+
result[1] = @graph_top + @graph_height
|
|
31
46
|
when 2
|
|
32
47
|
# only negative values
|
|
33
|
-
result[0] = @graph_top
|
|
34
|
-
result[1] = @graph_top + @graph_height * (1 - data_point)
|
|
48
|
+
result[0] = @graph_top
|
|
49
|
+
result[1] = @graph_top + @graph_height * (1 - data_point)
|
|
35
50
|
when 3
|
|
36
51
|
# positive and negative values
|
|
37
52
|
val = data_point - @minimum_value / @spread
|
|
38
|
-
result[0] = @graph_top + @graph_height * (1 - (val - @zero))
|
|
39
|
-
result[1] = @graph_top + @graph_height * (1 - @zero)
|
|
53
|
+
result[0] = @graph_top + @graph_height * (1 - (val - @zero))
|
|
54
|
+
result[1] = @graph_top + @graph_height * (1 - @zero)
|
|
40
55
|
else
|
|
41
56
|
result[0] = 0.0
|
|
42
57
|
result[1] = 0.0
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @private
|
|
4
|
+
module Gruff::BarValueLabel
|
|
5
|
+
using String::GruffCommify
|
|
6
|
+
|
|
7
|
+
# @private
|
|
8
|
+
class Base
|
|
9
|
+
attr_reader :coordinate, :value
|
|
10
|
+
|
|
11
|
+
def initialize(coordinate, value)
|
|
12
|
+
@coordinate = coordinate
|
|
13
|
+
@value = value
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @private
|
|
18
|
+
class Bar < Base
|
|
19
|
+
def prepare_rendering(format, _bar_width = 0)
|
|
20
|
+
left_x, left_y, right_x, _right_y = @coordinate
|
|
21
|
+
if format.is_a?(Proc)
|
|
22
|
+
val = format.call(@value)
|
|
23
|
+
else
|
|
24
|
+
val = sprintf(format || '%.2f', @value).commify
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
y = @value >= 0 ? left_y - 30 : left_y + 12
|
|
28
|
+
yield left_x + (right_x - left_x) / 2, y, val
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @private
|
|
33
|
+
class SideBar < Base
|
|
34
|
+
def prepare_rendering(format, bar_width = 0)
|
|
35
|
+
left_x, _left_y, right_x, right_y = @coordinate
|
|
36
|
+
if format.is_a?(Proc)
|
|
37
|
+
val = format.call(@value)
|
|
38
|
+
else
|
|
39
|
+
val = sprintf(format || '%.2f', @value).commify
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
x = @value >= 0 ? right_x + 40 : left_x - 40
|
|
43
|
+
yield x, right_y - bar_width / 2, val
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @private
|
|
48
|
+
class StackedBar
|
|
49
|
+
def initialize
|
|
50
|
+
@bars = []
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def add(bar, index)
|
|
54
|
+
bars = @bars[index] || []
|
|
55
|
+
bars << bar
|
|
56
|
+
@bars[index] = bars
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def prepare_rendering(format, bar_width = 0, &block)
|
|
60
|
+
@bars.each do |bars|
|
|
61
|
+
value = bars.sum(&:value)
|
|
62
|
+
bar = bars.last
|
|
63
|
+
bar_value_label = bar.class.new(bar.coordinate, value)
|
|
64
|
+
bar_value_label.prepare_rendering(format, bar_width, &block)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -7,10 +7,9 @@ module Gruff::Base::StackedMixin
|
|
|
7
7
|
# tsal: moved from Base 03 FEB 2007
|
|
8
8
|
def calculate_maximum_by_stack
|
|
9
9
|
# Get sum of each stack
|
|
10
|
-
max_hash = {}
|
|
10
|
+
max_hash = Hash.new { |h, k| h[k] = 0.0 }
|
|
11
11
|
store.data.each do |data_set|
|
|
12
12
|
data_set.points.each_with_index do |data_point, i|
|
|
13
|
-
max_hash[i] = 0.0 unless max_hash[i]
|
|
14
13
|
max_hash[i] += data_point.to_f
|
|
15
14
|
end
|
|
16
15
|
end
|
data/lib/gruff/histogram.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'histogram'
|
|
4
|
-
require 'gruff/base'
|
|
5
4
|
|
|
6
5
|
#
|
|
7
6
|
# Here's how to set up a Gruff::Histogram.
|
|
@@ -29,19 +28,21 @@ class Gruff::Histogram < Gruff::Bar
|
|
|
29
28
|
@data = []
|
|
30
29
|
end
|
|
31
30
|
|
|
32
|
-
def
|
|
31
|
+
def data(name, data_points = [], color = nil)
|
|
32
|
+
@data << [name, data_points, color]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def initialize_attributes
|
|
33
38
|
super
|
|
34
39
|
@bin_width = 10
|
|
35
40
|
@minimum_bin = nil
|
|
36
41
|
@maximum_bin = nil
|
|
37
42
|
end
|
|
38
|
-
private :
|
|
39
|
-
|
|
40
|
-
def data(name, data_points = [], color = nil)
|
|
41
|
-
@data << [name, data_points, color]
|
|
42
|
-
end
|
|
43
|
+
private :initialize_attributes
|
|
43
44
|
|
|
44
|
-
def
|
|
45
|
+
def setup_data
|
|
45
46
|
@data.each do |(name, data_points, color)|
|
|
46
47
|
bins, freqs = HistogramArray.new(data_points).histogram(bin_width: @bin_width, min: @minimum_bin, max: @maximum_bin)
|
|
47
48
|
bins.each_with_index do |bin, index|
|
data/lib/gruff/line.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 make a Gruff::Line.
|
|
7
5
|
#
|
|
@@ -30,7 +28,7 @@ class Gruff::Line < Gruff::Base
|
|
|
30
28
|
# default is +'circle'+, other options include square.
|
|
31
29
|
attr_writer :dot_style
|
|
32
30
|
|
|
33
|
-
# Hide parts of the graph to fit more
|
|
31
|
+
# Hide parts of the graph to fit more data points, or for a different appearance.
|
|
34
32
|
attr_writer :hide_dots, :hide_lines
|
|
35
33
|
|
|
36
34
|
# accessors for support of xy data.
|
|
@@ -39,6 +37,9 @@ class Gruff::Line < Gruff::Base
|
|
|
39
37
|
# accessors for support of xy data.
|
|
40
38
|
attr_writer :maximum_x_value
|
|
41
39
|
|
|
40
|
+
# The number of vertical lines shown.
|
|
41
|
+
attr_writer :marker_x_count
|
|
42
|
+
|
|
42
43
|
# Get the value if somebody has defined it.
|
|
43
44
|
def baseline_value
|
|
44
45
|
if @reference_lines.key?(:baseline)
|
|
@@ -80,29 +81,6 @@ class Gruff::Line < Gruff::Base
|
|
|
80
81
|
end
|
|
81
82
|
end
|
|
82
83
|
|
|
83
|
-
def initialize_store
|
|
84
|
-
@store = Gruff::Store.new(Gruff::Store::XYData)
|
|
85
|
-
end
|
|
86
|
-
private :initialize_store
|
|
87
|
-
|
|
88
|
-
def initialize_ivars
|
|
89
|
-
super
|
|
90
|
-
@reference_lines = {}
|
|
91
|
-
@reference_line_default_color = 'red'
|
|
92
|
-
@reference_line_default_width = 5
|
|
93
|
-
|
|
94
|
-
@hide_dots = @hide_lines = false
|
|
95
|
-
@maximum_x_value = nil
|
|
96
|
-
@minimum_x_value = nil
|
|
97
|
-
|
|
98
|
-
@line_width = nil
|
|
99
|
-
@dot_radius = nil
|
|
100
|
-
@dot_style = 'circle'
|
|
101
|
-
|
|
102
|
-
@show_vertical_markers = false
|
|
103
|
-
end
|
|
104
|
-
private :initialize_ivars
|
|
105
|
-
|
|
106
84
|
# This method allows one to plot a dataset with both X and Y data.
|
|
107
85
|
#
|
|
108
86
|
# @overload dataxy(name, x_data_points = [], y_data_points = [], color = nil)
|
|
@@ -134,7 +112,7 @@ class Gruff::Line < Gruff::Base
|
|
|
134
112
|
# g.data("Capples", [1, 1, 2, 2, 3, 3])
|
|
135
113
|
#
|
|
136
114
|
# # labels will be drawn at the x locations of the keys passed in.
|
|
137
|
-
# In this example the
|
|
115
|
+
# In this example the labels are drawn at x positions 2, 4, and 6:
|
|
138
116
|
# g.labels = {0 => '2003', 2 => '2004', 4 => '2005', 6 => '2006'}
|
|
139
117
|
# # The 0 => '2003' label will be ignored since it is outside the chart range.
|
|
140
118
|
def dataxy(name, x_data_points = [], y_data_points = [], color = nil)
|
|
@@ -154,12 +132,34 @@ class Gruff::Line < Gruff::Base
|
|
|
154
132
|
store.add(name, y_data_points, color, x_data_points)
|
|
155
133
|
end
|
|
156
134
|
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
def initialize_store
|
|
138
|
+
@store = Gruff::Store.new(Gruff::Store::XYData)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def initialize_attributes
|
|
142
|
+
super
|
|
143
|
+
@reference_lines = {}
|
|
144
|
+
@reference_line_default_color = 'red'
|
|
145
|
+
@reference_line_default_width = 5
|
|
146
|
+
|
|
147
|
+
@hide_dots = @hide_lines = false
|
|
148
|
+
@maximum_x_value = nil
|
|
149
|
+
@minimum_x_value = nil
|
|
150
|
+
@marker_x_count = nil
|
|
151
|
+
|
|
152
|
+
@line_width = nil
|
|
153
|
+
@dot_radius = nil
|
|
154
|
+
@dot_style = 'circle'
|
|
155
|
+
|
|
156
|
+
@show_vertical_markers = false
|
|
157
|
+
end
|
|
158
|
+
|
|
157
159
|
def draw_reference_line(reference_line, left, right, top, bottom)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
Gruff::Renderer::DashLine.new(config).render(left, top, right, bottom)
|
|
160
|
+
color = reference_line[:color] || @reference_line_default_color
|
|
161
|
+
width = reference_line[:width] || @reference_line_default_width
|
|
162
|
+
Gruff::Renderer::DashLine.new(renderer, color: color, width: width).render(left, top, right, bottom)
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def draw_horizontal_reference_line(reference_line)
|
|
@@ -172,11 +172,7 @@ class Gruff::Line < Gruff::Base
|
|
|
172
172
|
draw_reference_line(reference_line, index, index, @graph_top, @graph_top + @graph_height)
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
-
def
|
|
176
|
-
super
|
|
177
|
-
|
|
178
|
-
return unless data_given?
|
|
179
|
-
|
|
175
|
+
def draw_graph
|
|
180
176
|
# Check to see if more than one datapoint was given. NaN can result otherwise.
|
|
181
177
|
@x_increment = (column_count > 1) ? (@graph_width / (column_count - 1).to_f) : @graph_width
|
|
182
178
|
|
|
@@ -185,18 +181,6 @@ class Gruff::Line < Gruff::Base
|
|
|
185
181
|
draw_vertical_reference_line(curr_reference_line) if curr_reference_line.key?(:index)
|
|
186
182
|
end
|
|
187
183
|
|
|
188
|
-
if @show_vertical_markers
|
|
189
|
-
(0..column_count).each do |column|
|
|
190
|
-
x = @graph_left + @graph_width - column.to_f * @x_increment
|
|
191
|
-
|
|
192
|
-
Gruff::Renderer::Line.new(color: @marker_color).render(x, @graph_bottom, x, @graph_top)
|
|
193
|
-
#If the user specified a marker shadow color, draw a shadow just below it
|
|
194
|
-
if @marker_shadow_color
|
|
195
|
-
Gruff::Renderer::Line.new(color: @marker_shadow_color).render(x + 1, @graph_bottom, x + 1, @graph_top)
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
184
|
store.norm_data.each do |data_row|
|
|
201
185
|
prev_x = prev_y = nil
|
|
202
186
|
|
|
@@ -204,7 +188,7 @@ class Gruff::Line < Gruff::Base
|
|
|
204
188
|
|
|
205
189
|
data_row.coordinates.each_with_index do |(x_data, y_data), index|
|
|
206
190
|
if x_data.nil?
|
|
207
|
-
#use the old method: equally spaced points along the x-axis
|
|
191
|
+
# use the old method: equally spaced points along the x-axis
|
|
208
192
|
new_x = @graph_left + (@x_increment * index)
|
|
209
193
|
draw_label(new_x, index)
|
|
210
194
|
else
|
|
@@ -225,24 +209,20 @@ class Gruff::Line < Gruff::Base
|
|
|
225
209
|
circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.y_points.size * 2.5), 5.0)
|
|
226
210
|
|
|
227
211
|
if !@hide_lines && prev_x && prev_y
|
|
228
|
-
Gruff::Renderer::Line.new(color: data_row.color, width: stroke_width)
|
|
212
|
+
Gruff::Renderer::Line.new(renderer, color: data_row.color, width: stroke_width)
|
|
229
213
|
.render(prev_x, prev_y, new_x, new_y)
|
|
230
214
|
end
|
|
231
215
|
|
|
232
216
|
if one_point || !@hide_dots
|
|
233
|
-
Gruff::Renderer::Dot.new(@dot_style, color: data_row.color, width: stroke_width).render(new_x, new_y, circle_radius)
|
|
217
|
+
Gruff::Renderer::Dot.new(renderer, @dot_style, color: data_row.color, width: stroke_width).render(new_x, new_y, circle_radius)
|
|
234
218
|
end
|
|
235
219
|
|
|
236
220
|
prev_x = new_x
|
|
237
221
|
prev_y = new_y
|
|
238
222
|
end
|
|
239
223
|
end
|
|
240
|
-
|
|
241
|
-
Gruff::Renderer.finish
|
|
242
224
|
end
|
|
243
225
|
|
|
244
|
-
private
|
|
245
|
-
|
|
246
226
|
def setup_data
|
|
247
227
|
# Update the global min/max values for the x data
|
|
248
228
|
@maximum_x_value ||= store.max_x
|
|
@@ -265,6 +245,11 @@ private
|
|
|
265
245
|
super
|
|
266
246
|
end
|
|
267
247
|
|
|
248
|
+
def setup_drawing
|
|
249
|
+
@marker_x_count ||= column_count - 1
|
|
250
|
+
super
|
|
251
|
+
end
|
|
252
|
+
|
|
268
253
|
def normalize
|
|
269
254
|
return unless data_given?
|
|
270
255
|
|
|
@@ -283,6 +268,24 @@ private
|
|
|
283
268
|
super unless store.data.any?(&:x_points)
|
|
284
269
|
end
|
|
285
270
|
|
|
271
|
+
def draw_line_markers
|
|
272
|
+
# do all of the stuff for the horizontal lines on the y-axis
|
|
273
|
+
super
|
|
274
|
+
return if @hide_line_markers
|
|
275
|
+
|
|
276
|
+
(0..@marker_x_count).each do |index|
|
|
277
|
+
if @show_vertical_markers
|
|
278
|
+
x = @graph_left + @graph_width - index * @graph_width / @marker_x_count
|
|
279
|
+
|
|
280
|
+
Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
|
|
281
|
+
# If the user specified a marker shadow color, draw a shadow just below it
|
|
282
|
+
if @marker_shadow_color
|
|
283
|
+
Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x + 1, @graph_bottom, x + 1, @graph_top)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
286
289
|
def get_x_coord(x_data_point, width, offset)
|
|
287
290
|
x_data_point * width + offset
|
|
288
291
|
end
|