prawn-graph 0.0.4 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +16 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +1168 -0
  6. data/.travis.yml +17 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/CONTRIBUTORS.md +6 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +142 -0
  12. data/Rakefile +7 -43
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/lib/prawn-graph.rb +16 -0
  16. data/lib/prawn/graph/calculations.rb +1 -0
  17. data/lib/prawn/graph/calculations/layout_calculator.rb +108 -0
  18. data/lib/prawn/graph/chart_components.rb +2 -0
  19. data/lib/prawn/graph/chart_components/canvas.rb +138 -0
  20. data/lib/prawn/graph/chart_components/series_renderer.rb +173 -0
  21. data/lib/prawn/graph/charts.rb +4 -0
  22. data/lib/prawn/graph/charts/bar.rb +18 -0
  23. data/lib/prawn/graph/charts/base.rb +69 -0
  24. data/lib/prawn/graph/charts/legacy.rb +4 -0
  25. data/lib/prawn/graph/charts/legacy/bar.rb +28 -0
  26. data/lib/prawn/graph/charts/legacy/base.rb +193 -0
  27. data/lib/prawn/graph/charts/legacy/grid.rb +51 -0
  28. data/lib/prawn/graph/charts/legacy/line.rb +39 -0
  29. data/lib/prawn/graph/charts/line.rb +18 -0
  30. data/lib/prawn/graph/extension.rb +59 -0
  31. data/lib/prawn/graph/series.rb +79 -0
  32. data/lib/prawn/graph/theme.rb +41 -0
  33. data/lib/prawn/graph/version.rb +5 -0
  34. data/prawn-graph.gemspec +42 -0
  35. metadata +156 -80
  36. data/README.markdown +0 -64
  37. data/examples/example_helper.rb +0 -10
  38. data/examples/graph/advanced_bar_chart.rb +0 -22
  39. data/examples/graph/bar_chart.pdf +0 -185
  40. data/examples/graph/bar_chart.rb +0 -18
  41. data/examples/graph/line_chart.pdf +0 -219
  42. data/examples/graph/line_chart.rb +0 -18
  43. data/examples/graph/themed_bar_chart.rb +0 -18
  44. data/examples/graph/themed_line_chart.rb +0 -18
  45. data/lib/prawn/graph.rb +0 -94
  46. data/lib/prawn/graph/bar.rb +0 -64
  47. data/lib/prawn/graph/base.rb +0 -231
  48. data/lib/prawn/graph/chart.rb +0 -4
  49. data/lib/prawn/graph/errors.rb +0 -7
  50. data/lib/prawn/graph/grid.rb +0 -50
  51. data/lib/prawn/graph/line.rb +0 -74
  52. data/lib/prawn/graph/themes.rb +0 -116
  53. data/lib/prawn/graph/themes/37signals.yml +0 -14
  54. data/lib/prawn/graph/themes/keynote.yml +0 -14
  55. data/lib/prawn/graph/themes/monochome.yml +0 -8
  56. data/lib/prawn/graph/themes/odeo.yml +0 -14
@@ -1,231 +0,0 @@
1
- module Prawn
2
- module Chart
3
-
4
- # Prawn::Chart::Base implements the common methods shared by most of the graphs
5
- # and charts whcih will need to be plotted.
6
- #
7
- # All Prawn::Chart::Base instances and their children will have the following
8
- # associated with them:
9
- #
10
- # 1. A Prawn::Chart::Grid which is where the graph will be drawn
11
- # 2. A refernce to the Prawn::Document being affected
12
- # 3. A set of data to be plotted.
13
- #
14
- # A public draw method is available which does what it says on the tin and...
15
- # well.. draws the graph on the document it has a reference to.
16
- #
17
- class Base
18
-
19
- attr_accessor :grid, :headings, :values, :highest_value, :document, :colour
20
-
21
- # Returns a new instance of a graph to be drawn, really only useful for the
22
- # subclasses which actually have a plot_values method declared so the data
23
- # is actually rendered as a graph.
24
- #
25
- # Takes an Array of +data+, which should contain complete rows of data for
26
- # values to be plotted; a reference to a +document+ which should be an
27
- # instance of Prawn::Document and an +options+ with at least a value for :at
28
- # specified.
29
- #
30
- # Options are:
31
- #
32
- # :at , which should be an Array representing the point at which the graph
33
- # should be drawn.
34
- #
35
- # :title, the title for this graph, wil be rendered centered to the top of
36
- # the Grid.
37
- #
38
- # :label_x, a label to be shown along the X axis of he graph, rendered centered
39
- # on the grid.
40
- #
41
- # :label_y, a label to be shown along the Y axis of he graph, rendered centered
42
- # on the grid and rotated to be perpendicular to the axis.
43
- #
44
- # :theme, the theme to be used to draw this graph, defaults to monochrome.
45
- #
46
- def initialize(data, document, options = {})
47
- if options[:at].nil? || options[:at].empty?
48
- raise Prawn::Errors::NoGraphStartSet,
49
- "you must specify options[:at] as the coordinates where you" +
50
- " wish this graph to be drawn from."
51
- end
52
- opts = { :theme => Prawn::Chart::Themes.monochrome, :width => 500, :height => 200, :spacing => 20 }.merge(options)
53
- (@headings, @values, @highest_value) = process_the data
54
- (grid_x_start, grid_y_start, grid_width, grid_height) = parse_sizing_from opts
55
- @colour = (!opts[:use_color].nil? || !opts[:use_colour].nil?)
56
- @document = document
57
- @theme = opts[:theme]
58
- off = 20
59
- @grid = Prawn::Chart::Grid.new(grid_x_start, grid_y_start, grid_width, grid_height, opts[:spacing], document, @theme)
60
- end
61
-
62
- # Draws the graph on the document which we have a reference to.
63
- #
64
- def draw
65
- draw_bounding_box
66
- @grid.draw
67
- label_axes
68
- if @title
69
- draw_title
70
- end
71
- plot_values
72
- if @x_label
73
- draw_x_axis_label
74
- end
75
- if @y_label
76
- draw_y_axis_label
77
- end
78
- reset
79
- end
80
-
81
- private
82
-
83
- def draw_bounding_box
84
- @document.fill_color @theme.background_colour
85
- @document.fill_and_stroke_rectangle [(@point.first - 10), (@point.last + ( @total_height + 40 ))], @document.bounds.width, (@total_height + 40)
86
- @document.fill_color '000000'
87
- end
88
-
89
- def label_axes
90
- @document.fill_color @theme.font_colour
91
- base_x = @grid.start_x + 1
92
- base_y = @grid.start_y + 1
93
-
94
- # Put the values up the Y Axis
95
- #
96
- @document.draw_text @highest_value, :at => [base_x - 15, base_y + @grid.height], :size => 5
97
- @document.draw_text '0', :at => [base_x - 15, base_y ], :size => 5
98
-
99
- # Put the column headings along the X Axis
100
- #
101
- point_spacing = calculate_plot_spacing
102
- last_position = base_x + (point_spacing / 2)
103
- @headings.each do |heading|
104
- @document.draw_text heading, :at => [last_position, base_y - 15 ], :size => 5
105
- last_position += point_spacing
106
- end
107
- @document.fill_color @theme.background_colour
108
- end
109
-
110
- def draw_title
111
- @document.fill_color @theme.font_colour
112
- x_coord = calculate_x_axis_center_point(@title, 10)
113
- y_coord = @grid.start_y + @grid.height + 10
114
- @document.draw_text @title, :at => [x_coord, y_coord] ,:size => 10
115
- @document.fill_color @theme.background_colour
116
- end
117
-
118
- def draw_x_axis_label
119
- @document.fill_color @theme.font_colour
120
- x_coord = calculate_x_axis_center_point(@x_label, 8)
121
- y_coord = @grid.start_y - 30
122
- @document.draw_text @x_label, :at => [x_coord, y_coord] ,:size => 8
123
- @document.fill_color @theme.background_colour
124
- end
125
-
126
- def draw_y_axis_label
127
- @document.fill_color @theme.font_colour
128
- y_coord = calculate_y_axis_center_point(@y_label, 8)
129
- x_coord = @grid.start_x - 30
130
- @document.draw_text @y_label, :at => [x_coord, y_coord] ,:size => 8, :rotate => 90
131
- @document.fill_color @theme.background_colour
132
- end
133
-
134
- # All subclasses of Prawn::Chart::Base must implement thier own plot_values
135
- # method, which does the actual real heavy lifting of drawing the graph.
136
- #
137
- def plot_values
138
- raise Prawn::Errors::NoPlotValuesMethod, 'subclasses of Prawn::Chart::Base must implement '
139
- + 'their own plot_values method.'
140
- end
141
-
142
- def reset
143
- @document.line_width 1
144
- @document.stroke_color '000000'
145
- @document.fill_color '000000'
146
- @document.move_to @grid.point
147
- end
148
-
149
-
150
- # Utility methods for dealing with working out where things should be
151
- # the calculations and such done here are all very rough, but are
152
- # sufficient for now to plot just what we need.
153
- #
154
-
155
-
156
- def parse_sizing_from(o)
157
- x_offset = 15
158
- y_offset = 0
159
- move_y_up = 0
160
- grid_width = o[:width]
161
- grid_height = o[:height]
162
-
163
- @total_width = o[:width]
164
- @total_height = o[:height]
165
- @point = o[:at].dup
166
-
167
- # Make room for the title if we're choosing to Render it.
168
- #
169
- if o[:title]
170
- @title = o[:title]
171
- y_offset += 10
172
- end
173
-
174
- # Make room for X Axis labels if we're using them.
175
- #
176
- if o[:label_x]
177
- y_offset += 30
178
- move_y_up += 30
179
- @x_label = o[:label_x]
180
- end
181
-
182
- # Make room for Y Axis labels if we're using them.
183
- #
184
- if o[:label_y]
185
- @y_label = o[:label_y]
186
- x_offset += 15
187
- end
188
-
189
-
190
- # Return the values calculated here.
191
- #
192
- [ (o[:at][0] + x_offset), (o[:at][1] + move_y_up + 20), (grid_width - (x_offset - 20)), (grid_height - y_offset) ]
193
- end
194
-
195
- def process_the(data_array)
196
- col = []
197
- val = []
198
- data_array.each { |i| val << i[1]; col << i[0] }
199
- [ col, val ,val.sort.last ]
200
- end
201
-
202
- def calculate_x_axis_center_point(text, text_size, graph_start_x = @grid.start_x, graph_width = @grid.width)
203
- ((graph_start_x + (graph_width / 2)) - ((text.length * text_size) / 4))
204
- end
205
- alias calculate_x_axis_centre_point calculate_x_axis_center_point
206
-
207
- def calculate_y_axis_center_point(text, text_size, graph_start_y = @grid.start_y, graph_height = @grid.height)
208
- ((graph_start_y + (graph_height / 2)) - ((text.length * text_size) / 4))
209
- end
210
- alias calculate_y_axis_centre_point calculate_y_axis_center_point
211
-
212
- def calculate_plot_spacing
213
- (@grid.width / @values.nitems)
214
- end
215
-
216
- def calculate_bar_width
217
- calculate_plot_spacing / 2
218
- end
219
-
220
- def calculate_point_height_from(column_value)
221
- cv = BigDecimal("#{column_value}")
222
- hv = BigDecimal("#{@highest_value}")
223
- gh = BigDecimal("#{@grid.height}")
224
- percentage = (cv / (hv / 100))
225
- ((gh / 100) * percentage).to_i
226
- end
227
-
228
-
229
- end
230
- end
231
- end
@@ -1,4 +0,0 @@
1
- module Prawn
2
- module Chart
3
- end
4
- end
@@ -1,7 +0,0 @@
1
- module Prawn
2
- module Errors
3
- NoGraphData = Class.new(StandardError)
4
- NoGraphStartSet = Class.new(StandardError)
5
- NoPlotValuesMethod = Class.new(StandardError)
6
- end
7
- end
@@ -1,50 +0,0 @@
1
- module Prawn
2
- module Chart
3
-
4
- # Prawn::Chart::Grid represents the area whcih your data will be plotted. It
5
- # is drawn before your data is plotted and serves to mark where the axes of
6
- # your plot will be and to give an indication of scale.
7
- #
8
- class Grid
9
-
10
- attr_accessor :width, :height, :point, :spacing, :document
11
-
12
- def initialize(grid_x_start, grid_y_start, grid_width, grid_height, spacing, document, theme)
13
- @point = [grid_x_start, grid_y_start]
14
- @width = grid_width
15
- @height = grid_height
16
- @spacing = spacing
17
- @document = document
18
- @theme = theme
19
- end
20
-
21
- def start_x; @point.first; end
22
- def start_y; @point.last; end
23
-
24
- # Draws the Grid on the specified Prawn::Document
25
- #
26
- def draw
27
- @document.stroke_color @theme.marker_colour
28
- if @theme.stroke_grid_markers?
29
- (@height / @spacing).times do |x|
30
- offset = @spacing * (x + 1)
31
- @document.move_to [@point.first, (@point.last + offset)]
32
- @document.line_width(0.5)
33
- @document.stroke_line_to([(@point.first + @width), (@point.last + offset)])
34
- end
35
- end
36
- @document.move_to @point
37
- @document.line_width(2)
38
- @document.stroke_line_to([@point.first, @point.last + @height])
39
- @document.move_to @point
40
- @document.line_width(2)
41
- @document.stroke_line_to([(@point.first + @width), @point.last])
42
- @document.move_to @point.first, (@point.last + height)
43
- @document.stroke_color '000000'
44
- @document.line_width(1)
45
- @document.move_to @point
46
- end
47
-
48
- end
49
- end
50
- end
@@ -1,74 +0,0 @@
1
- module Prawn
2
- module Chart
3
-
4
- # Prawn::Chart::Line plots its values as a Line graph, relatively
5
- # sized to fit within the space defined by the Prawn::Chart::Grid
6
- # associated with it.
7
- #
8
- # Call to new will return a new instance of Prawn::Chart::Line ready to
9
- # be rendered.
10
- #
11
- # Takes an Array of +data+, which should contain complete rows of data for
12
- # values to be plotted; a reference to a +document+ which should be an
13
- # instance of Prawn::Document and an +options+ with at least a value for :at
14
- # specified.
15
- #
16
- # Options are:
17
- #
18
- # :at , which should be an Array representing the point at which the graph
19
- # should be drawn.
20
- #
21
- # :title, the title for this graph, wil be rendered centered to the top of
22
- # the Grid.
23
- #
24
- # :label_x, a label to be shown along the X axis of he graph, rendered centered
25
- # on the grid.
26
- #
27
- # :label_y, a label to be shown along the Y axis of he graph, rendered centered
28
- # on the grid and rotated to be perpendicular to the axis.
29
- #
30
- # Data should be formatted like:
31
- #
32
- # [
33
- # [ 'Column Heading', SomeValue ],
34
- # [ 'Column Heading', SomeValue ],
35
- # [ 'Column Heading', SomeValue ],
36
- # [ 'Column Heading', SomeValue ],
37
- # [ 'Column Heading', SomeValue ],
38
- # [ 'Column Heading', SomeValue ]
39
- # ]
40
- #
41
-
42
- class Line < Base
43
-
44
- private
45
-
46
- def plot_values
47
- base_x = @grid.start_x + 1
48
- base_y = @grid.start_y + 1
49
- p = [ [base_x, base_y] ]
50
- bar_width = calculate_bar_width
51
- @document.line_width bar_width
52
- last_position = base_x + bar_width
53
- point_spacing = calculate_plot_spacing
54
- @values.each do |value|
55
- @document.move_to [base_x + last_position, base_y]
56
- bar_height = calculate_point_height_from value
57
- point = [base_x + last_position, base_y + bar_height]
58
- p << point
59
- @document.fill_color @theme.colours.first
60
- @document.fill_circle_at point, :radius => 1
61
- last_position += point_spacing
62
- end
63
- @document.line_width 2
64
- @document.stroke_color @theme.colours.first
65
- p.each_with_index do |point,i|
66
- next if point == p.last
67
- @document.move_to point
68
- @document.stroke_line_to p[i+1]
69
- end
70
- end
71
-
72
- end
73
- end
74
- end
@@ -1,116 +0,0 @@
1
- require 'yaml'
2
-
3
- module Prawn
4
- module Chart
5
-
6
- # Themes serves as a point of interaction between the user and the underlying
7
- # collection of themes made available to Prawn::Graph.
8
- #
9
- class Themes
10
-
11
- # Called once when Prawn::Graph is loaded, initializes the list of
12
- # themes currently bundled. If you have your own custom theme you'd
13
- # like to use instead, use _register_theme and give it the path to
14
- # your theme file.
15
- #
16
- def self.initialize_themes
17
- path = File.expand_path(File.dirname(__FILE__) + '/themes/')
18
- Dir.open(path) do |dir|
19
- dir.each do |file|
20
- _register_theme(path + '/' + file) if file.include?('.yml')
21
- end
22
- end
23
- end
24
-
25
- # Adds the theme defined by the yaml file specified to the mapping of
26
- # registered themes stored in +@@_themes_list+. Converts the YAML object
27
- # into a Theme object for use in the application.
28
- #
29
- def self._register_theme(theme_file_path)
30
- theme = Theme.new(YAML.load(IO.read(File.expand_path(theme_file_path))))
31
- if !defined? @@_themes_list
32
- @@_themes_list = {}
33
- end
34
- @@_themes_list[theme.name.to_sym] = theme
35
- end
36
-
37
- # Returns an array of the themes currently registered.
38
- #
39
- def self.list
40
- @@_themes_list.keys
41
- end
42
-
43
- protected
44
-
45
- # Hook into method_missing to allow us to do things like:
46
- # Prawn::Chart::Themes.theme_name
47
- # To return the theme object being looked for.
48
- #
49
- def self.method_missing(method, *args)
50
- if @@_themes_list.keys.include?(method)
51
- return @@_themes_list[method]
52
- end
53
- end
54
-
55
-
56
- class Theme
57
- attr_accessor :name, :title, :colours, :font_colour, :background_colour, :marker_colour
58
-
59
- # Creates a new theme from a theme hash. The hash comes from the
60
- # library parsing YAML definitions of a theme.
61
- #
62
- def initialize(theme_hash)
63
- @name = theme_hash['name']
64
- @title = theme_hash['title']
65
-
66
- if theme_hash.keys.include?('colours')
67
- @colours = theme_hash['colours']
68
- elsif theme_hash.keys.include?('colors')
69
- @colours = theme_hash['colors']
70
- end
71
-
72
- if theme_hash.keys.include?('font_colour')
73
- @font_colour = theme_hash['font_colour']
74
- elsif theme_hash.keys.include?('font_color')
75
- @font_colour = theme_hash['font_color']
76
- end
77
-
78
- if theme_hash.keys.include?('background_colour')
79
- @background_colour = theme_hash['background_colour']
80
- elsif theme_hash.keys.include?('background_color')
81
- @background_colour = theme_hash['background_color']
82
- end
83
-
84
- if theme_hash.keys.include?('marker_colour')
85
- @marker_colour = theme_hash['marker_colour']
86
- elsif theme_hash.keys.include?('marker_color')
87
- @marker_colour = theme_hash['marker_color']
88
- end
89
-
90
- @stroke_grid_markers = theme_hash['stroke_grid_markers'].to_i
91
- end
92
-
93
- # Returns the next colour in the array of colours associated
94
- # with this theme. If it gets to the end, it starts again from
95
- # the beginning.
96
- #
97
- def next_colour
98
- unless @current_colour
99
- @current_colour = 0
100
- return @colours[0]
101
- end
102
- @current_colour += 1
103
- @current_colour = 0 if @current_colour == @colours.nitems
104
- @colours[@current_colour]
105
- end
106
- alias next_color next_colour
107
-
108
- def stroke_grid_markers?
109
- @stroke_grid_markers == 1
110
- end
111
-
112
- end
113
- end
114
-
115
- end
116
- end