gruff 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +14 -0
  3. data/.rubocop.yml +16 -0
  4. data/.rubocop_todo.yml +923 -0
  5. data/.travis.yml +21 -14
  6. data/{History.txt → CHANGELOG.md} +32 -25
  7. data/README.md +3 -2
  8. data/Rakefile +27 -18
  9. data/assets/bubble.png +0 -0
  10. data/assets/city_scene/background/0000.png +0 -0
  11. data/assets/city_scene/background/0600.png +0 -0
  12. data/assets/city_scene/background/2000.png +0 -0
  13. data/assets/city_scene/clouds/cloudy.png +0 -0
  14. data/assets/city_scene/clouds/partly_cloudy.png +0 -0
  15. data/assets/city_scene/clouds/stormy.png +0 -0
  16. data/assets/city_scene/grass/default.png +0 -0
  17. data/assets/city_scene/haze/true.png +0 -0
  18. data/assets/city_scene/number_sample/1.png +0 -0
  19. data/assets/city_scene/number_sample/2.png +0 -0
  20. data/assets/city_scene/number_sample/default.png +0 -0
  21. data/assets/city_scene/sky/0000.png +0 -0
  22. data/assets/city_scene/sky/0200.png +0 -0
  23. data/assets/city_scene/sky/0400.png +0 -0
  24. data/assets/city_scene/sky/0600.png +0 -0
  25. data/assets/city_scene/sky/0800.png +0 -0
  26. data/assets/city_scene/sky/1000.png +0 -0
  27. data/assets/city_scene/sky/1200.png +0 -0
  28. data/assets/city_scene/sky/1400.png +0 -0
  29. data/assets/city_scene/sky/1500.png +0 -0
  30. data/assets/city_scene/sky/1700.png +0 -0
  31. data/assets/city_scene/sky/2000.png +0 -0
  32. data/assets/pc306715.jpg +0 -0
  33. data/assets/plastik/blue.png +0 -0
  34. data/assets/plastik/green.png +0 -0
  35. data/assets/plastik/red.png +0 -0
  36. data/gruff.gemspec +12 -10
  37. data/lib/gruff.rb +2 -2
  38. data/lib/gruff/accumulator_bar.rb +2 -2
  39. data/lib/gruff/area.rb +1 -4
  40. data/lib/gruff/bar.rb +12 -13
  41. data/lib/gruff/bar_conversion.rb +11 -11
  42. data/lib/gruff/base.rb +36 -36
  43. data/lib/gruff/bezier.rb +1 -2
  44. data/lib/gruff/bullet.rb +7 -10
  45. data/lib/gruff/deprecated.rb +10 -11
  46. data/lib/gruff/dot.rb +3 -4
  47. data/lib/gruff/line.rb +13 -14
  48. data/lib/gruff/mini/bar.rb +3 -3
  49. data/lib/gruff/mini/legend.rb +7 -8
  50. data/lib/gruff/mini/pie.rb +6 -6
  51. data/lib/gruff/mini/side_bar.rb +7 -7
  52. data/lib/gruff/net.rb +2 -8
  53. data/lib/gruff/photo_bar.rb +9 -12
  54. data/lib/gruff/pie.rb +6 -6
  55. data/lib/gruff/scatter.rb +47 -51
  56. data/lib/gruff/scene.rb +17 -19
  57. data/lib/gruff/side_bar.rb +5 -8
  58. data/lib/gruff/side_stacked_bar.rb +24 -26
  59. data/lib/gruff/spider.rb +14 -15
  60. data/lib/gruff/stacked_area.rb +12 -16
  61. data/lib/gruff/stacked_bar.rb +50 -52
  62. data/lib/gruff/stacked_mixin.rb +2 -3
  63. data/lib/gruff/themes.rb +32 -33
  64. data/lib/gruff/version.rb +1 -1
  65. metadata +23 -67
  66. data/RELEASE.md +0 -30
  67. data/test/gruff_test_case.rb +0 -152
  68. data/test/image_compare.rb +0 -58
  69. data/test/test_accumulator_bar.rb +0 -51
  70. data/test/test_area.rb +0 -134
  71. data/test/test_bar.rb +0 -505
  72. data/test/test_base.rb +0 -33
  73. data/test/test_bezier.rb +0 -33
  74. data/test/test_bullet.rb +0 -26
  75. data/test/test_dot.rb +0 -263
  76. data/test/test_labels_for_null_data.rb +0 -27
  77. data/test/test_legend.rb +0 -68
  78. data/test/test_line.rb +0 -674
  79. data/test/test_mini_bar.rb +0 -33
  80. data/test/test_mini_pie.rb +0 -25
  81. data/test/test_mini_side_bar.rb +0 -36
  82. data/test/test_net.rb +0 -231
  83. data/test/test_photo.rb +0 -41
  84. data/test/test_pie.rb +0 -194
  85. data/test/test_scatter.rb +0 -270
  86. data/test/test_scene.rb +0 -100
  87. data/test/test_side_bar.rb +0 -56
  88. data/test/test_sidestacked_bar.rb +0 -105
  89. data/test/test_spider.rb +0 -226
  90. data/test/test_stacked_area.rb +0 -52
  91. data/test/test_stacked_bar.rb +0 -68
@@ -50,10 +50,10 @@ class Gruff::Pie < Gruff::Base
50
50
 
51
51
  def options
52
52
  {
53
- :zero_degree => zero_degree,
54
- :hide_labels_less_than => hide_labels_less_than,
55
- :text_offset_percentage => text_offset_percentage,
56
- :show_values_as_labels => show_values_as_labels
53
+ zero_degree: zero_degree,
54
+ hide_labels_less_than: hide_labels_less_than,
55
+ text_offset_percentage: text_offset_percentage,
56
+ show_values_as_labels: show_values_as_labels
57
57
  }
58
58
  end
59
59
 
@@ -78,7 +78,7 @@ class Gruff::Pie < Gruff::Base
78
78
  trigger_final_draw
79
79
  end
80
80
 
81
- private
81
+ private
82
82
 
83
83
  def slices
84
84
  @slices ||= begin
@@ -163,7 +163,7 @@ class Gruff::Pie < Gruff::Base
163
163
 
164
164
  def process_label_for(slice)
165
165
  if slice.percentage >= hide_labels_less_than
166
- x, y = label_coordinates_for slice
166
+ x, y = label_coordinates_for slice
167
167
 
168
168
  @d = draw_label(x, y, slice.label)
169
169
  end
@@ -6,30 +6,30 @@ require File.dirname(__FILE__) + '/base'
6
6
  # g.data(:apples, [1,2,3,4], [4,3,2,1])
7
7
  # g.data('oranges', [5,7,8], [4,1,7])
8
8
  # g.write('test/output/scatter.png')
9
- #
9
+ #
10
10
  #
11
11
  class Gruff::Scatter < Gruff::Base
12
12
 
13
13
  # Maximum X Value. The value will get overwritten by the max in the
14
- # datasets.
14
+ # datasets.
15
15
  attr_accessor :maximum_x_value
16
-
17
- # Minimum X Value. The value will get overwritten by the min in the
18
- # datasets.
16
+
17
+ # Minimum X Value. The value will get overwritten by the min in the
18
+ # datasets.
19
19
  attr_accessor :minimum_x_value
20
-
20
+
21
21
  # The number of vertical lines shown for reference
22
22
  attr_accessor :marker_x_count
23
-
23
+
24
24
  #~ # Draw a dashed horizontal line at the given y value
25
25
  #~ attr_accessor :baseline_y_value
26
-
26
+
27
27
  #~ # Color of the horizontal baseline
28
28
  #~ attr_accessor :baseline_y_color
29
-
29
+
30
30
  #~ # Draw a dashed horizontal line at the given y value
31
31
  #~ attr_accessor :baseline_x_value
32
-
32
+
33
33
  #~ # Color of the horizontal baseline
34
34
  #~ attr_accessor :baseline_x_color
35
35
 
@@ -51,8 +51,7 @@ class Gruff::Scatter < Gruff::Base
51
51
  # Allow passing lambdas to format labels
52
52
  attr_accessor :y_axis_label_format
53
53
  attr_accessor :x_axis_label_format
54
-
55
-
54
+
56
55
  # Gruff::Scatter takes the same parameters as the Gruff::Line graph
57
56
  #
58
57
  # ==== Example
@@ -91,7 +90,7 @@ class Gruff::Scatter < Gruff::Base
91
90
  super
92
91
  return unless @has_data
93
92
 
94
- # Check to see if more than one datapoint was given. NaN can result otherwise.
93
+ # Check to see if more than one datapoint was given. NaN can result otherwise.
95
94
  @x_increment = (@column_count > 1) ? (@graph_width / (@column_count - 1).to_f) : @graph_width
96
95
 
97
96
  #~ if (defined?(@norm_y_baseline)) then
@@ -106,13 +105,13 @@ class Gruff::Scatter < Gruff::Base
106
105
  #~ end
107
106
 
108
107
  #~ if (defined?(@norm_x_baseline)) then
109
-
108
+
110
109
  #~ end
111
110
 
112
- @norm_data.each do |data_row|
111
+ @norm_data.each do |data_row|
113
112
  data_row[DATA_VALUES_INDEX].each_with_index do |data_point, index|
114
113
  x_value = data_row[DATA_VALUES_X_INDEX][index]
115
- next if data_point.nil? || x_value.nil?
114
+ next if data_point.nil? || x_value.nil?
116
115
 
117
116
  new_x = get_x_coord(x_value, @graph_width, @graph_left)
118
117
  new_y = @graph_top + (@graph_height - data_point * @graph_height)
@@ -130,7 +129,7 @@ class Gruff::Scatter < Gruff::Base
130
129
 
131
130
  @d.draw(@base_image)
132
131
  end
133
-
132
+
134
133
  # The first parameter is the name of the dataset. The next two are the
135
134
  # x and y axis data points contain in their own array in that respective
136
135
  # order. The final parameter is the color.
@@ -146,8 +145,8 @@ class Gruff::Scatter < Gruff::Base
146
145
  #
147
146
  # ==== Parameters
148
147
  # name:: String or Symbol containing the name of the dataset.
149
- # x_data_points:: An Array of of x-axis data points.
150
- # y_data_points:: An Array of of y-axis data points.
148
+ # x_data_points:: An Array of of x-axis data points.
149
+ # y_data_points:: An Array of of y-axis data points.
151
150
  # color:: The hex string for the color of the dataset. Defaults to nil.
152
151
  #
153
152
  # ==== Exceptions
@@ -168,64 +167,63 @@ class Gruff::Scatter < Gruff::Base
168
167
  # g.data('oranges', [1,1,1], [2,3,4])
169
168
  # g.data('bitter_melon', [3,5,6], [6,7,8], '#000000')
170
169
  #
171
- def data(name, x_data_points=[], y_data_points=[], color=nil)
172
-
170
+ def data(name, x_data_points = [], y_data_points = [], color = nil)
173
171
  raise ArgumentError, 'Data Points contain nil Value!' if x_data_points.include?(nil) || y_data_points.include?(nil)
174
172
  raise ArgumentError, 'x_data_points is empty!' if x_data_points.empty?
175
173
  raise ArgumentError, 'y_data_points is empty!' if y_data_points.empty?
176
174
  raise ArgumentError, 'x_data_points.length != y_data_points.length!' if x_data_points.length != y_data_points.length
177
-
175
+
178
176
  # Call the existing data routine for the y axis data
179
177
  super(name, y_data_points, color)
180
-
178
+
181
179
  #append the x data to the last entry that was just added in the @data member
182
- last_elem = @data.length()-1
180
+ last_elem = @data.length() - 1
183
181
  @data[last_elem] << x_data_points
184
-
182
+
185
183
  if @maximum_x_value.nil? && @minimum_x_value.nil?
186
184
  @maximum_x_value = @minimum_x_value = x_data_points.first
187
185
  end
188
-
186
+
189
187
  @maximum_x_value = x_data_points.max > @maximum_x_value ?
190
188
  x_data_points.max : @maximum_x_value
191
189
  @minimum_x_value = x_data_points.min < @minimum_x_value ?
192
190
  x_data_points.min : @minimum_x_value
193
191
  end
194
-
192
+
195
193
  protected
196
-
194
+
197
195
  def calculate_spread #:nodoc:
198
196
  super
199
197
  @x_spread = @maximum_x_value.to_f - @minimum_x_value.to_f
200
198
  @x_spread = @x_spread > 0 ? @x_spread : 1
201
199
  end
202
-
203
- def normalize(force=nil)
204
- if @norm_data.nil? || force
200
+
201
+ def normalize(force = nil)
202
+ if @norm_data.nil? || force
205
203
  @norm_data = []
206
204
  return unless @has_data
207
-
205
+
208
206
  @data.each do |data_row|
209
207
  norm_data_points = [data_row[DATA_LABEL_INDEX]]
210
- norm_data_points << data_row[DATA_VALUES_INDEX].map do |r|
211
- (r.to_f - @minimum_value.to_f) / @spread
212
- end
208
+ norm_data_points << data_row[DATA_VALUES_INDEX].map do |r|
209
+ (r.to_f - @minimum_value.to_f) / @spread
210
+ end
213
211
  norm_data_points << data_row[DATA_COLOR_INDEX]
214
- norm_data_points << data_row[DATA_VALUES_X_INDEX].map do |r|
215
- (r.to_f - @minimum_x_value.to_f) / @x_spread
216
- end
212
+ norm_data_points << data_row[DATA_VALUES_X_INDEX].map do |r|
213
+ (r.to_f - @minimum_x_value.to_f) / @x_spread
214
+ end
217
215
  @norm_data << norm_data_points
218
216
  end
219
217
  end
220
218
  #~ @norm_y_baseline = (@baseline_y_value.to_f / @maximum_value.to_f) if @baseline_y_value
221
219
  #~ @norm_x_baseline = (@baseline_x_value.to_f / @maximum_x_value.to_f) if @baseline_x_value
222
220
  end
223
-
221
+
224
222
  def draw_line_markers
225
223
  # do all of the stuff for the horizontal lines on the y-axis
226
224
  super
227
225
  return if @hide_line_markers
228
-
226
+
229
227
  @d = @d.stroke_antialias false
230
228
 
231
229
  if @x_axis_increment.nil?
@@ -249,7 +247,7 @@ protected
249
247
  @minimum_x_value = @minimum_x_value.floor
250
248
  calculate_spread
251
249
  normalize(true)
252
-
250
+
253
251
  @marker_count = (@x_spread / @x_axis_increment).to_i
254
252
  @x_increment = @x_axis_increment
255
253
  end
@@ -257,7 +255,6 @@ protected
257
255
 
258
256
  # Draw vertical line markers and annotate with numbers
259
257
  (0..@marker_x_count).each do |index|
260
-
261
258
  # TODO Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
262
259
  if @enable_vertical_line_markers
263
260
  x = @graph_left + @graph_width - index.to_f * @increment_x_scaled
@@ -277,18 +274,17 @@ protected
277
274
  @d.pointsize = scale_fontsize(@marker_font_size)
278
275
  @d.gravity = NorthGravity
279
276
  @d.rotation = -90.0 if @use_vertical_x_labels
280
- @d = @d.annotate_scaled(@base_image,
281
- 1.0, 1.0,
282
- x_offset, y_offset,
283
- vertical_label(marker_label, @x_increment), @scale)
277
+ @d = @d.annotate_scaled(@base_image,
278
+ 1.0, 1.0,
279
+ x_offset, y_offset,
280
+ vertical_label(marker_label, @x_increment), @scale)
284
281
  @d.rotation = 90.0 if @use_vertical_x_labels
285
282
  end
286
283
  end
287
-
284
+
288
285
  @d = @d.stroke_antialias true
289
286
  end
290
287
 
291
-
292
288
  def label(value, increment)
293
289
  if @y_axis_label_format
294
290
  @y_axis_label_format.call(value)
@@ -304,11 +300,11 @@ protected
304
300
  label(value, increment)
305
301
  end
306
302
  end
307
-
303
+
308
304
  private
309
-
305
+
310
306
  def get_x_coord(x_data_point, width, offset) #:nodoc:
311
307
  x_data_point * width + offset
312
308
  end
313
-
309
+
314
310
  end # end Gruff::Scatter
@@ -1,10 +1,9 @@
1
-
2
1
  require "observer"
3
2
  require File.dirname(__FILE__) + '/base'
4
3
 
5
4
  ##
6
5
  # A scene is a non-linear graph that assembles layers together to tell a story.
7
- # Layers are folders with appropriately named files (see below). You can group
6
+ # Layers are folders with appropriately named files (see below). You can group
8
7
  # layers and control them together or just set their values individually.
9
8
  #
10
9
  # Examples:
@@ -13,7 +12,7 @@ require File.dirname(__FILE__) + '/base'
13
12
  # * A traffic map that shows red lines on streets that are crowded and green on free-flowing ones.
14
13
  #
15
14
  # Usage:
16
- #
15
+ #
17
16
  # g = Gruff::Scene.new("500x100", "path/to/city_scene_directory")
18
17
  #
19
18
  # # Define order of layers, back to front
@@ -40,7 +39,7 @@ require File.dirname(__FILE__) + '/base'
40
39
  # * If there is a file named 'default.png', it will be used unless other input values are set for the corresponding layer.
41
40
 
42
41
  class Gruff::Scene < Gruff::Base
43
-
42
+
44
43
  # An array listing the foldernames that will be rendered, from back to front.
45
44
  #
46
45
  # g.layers = %w(sky clouds buildings street people)
@@ -50,13 +49,13 @@ class Gruff::Scene < Gruff::Base
50
49
  def initialize(target_width, base_dir)
51
50
  @base_dir = base_dir
52
51
  @groups = {}
53
- @layers = []
52
+ @layers = []
54
53
  super target_width
55
54
  end
56
55
 
57
56
  def draw
58
57
  # Join all the custom paths and filter out the empty ones
59
- image_paths = @layers.map { |layer| layer.path }.select { |path| !path.empty? }
58
+ image_paths = @layers.map { |layer| layer.path }.reject { |path| path.empty? }
60
59
  images = Magick::ImageList.new(*image_paths)
61
60
  @base_image = images.flatten_images
62
61
  end
@@ -102,9 +101,8 @@ private
102
101
  end
103
102
  end
104
103
  end
105
-
106
- end
107
104
 
105
+ end
108
106
 
109
107
  class Gruff::Group
110
108
 
@@ -117,31 +115,30 @@ class Gruff::Group
117
115
  layer.observe self
118
116
  end
119
117
  end
120
-
118
+
121
119
  def send_updates(value)
122
120
  changed
123
121
  notify_observers value
124
122
  end
125
-
126
- end
127
123
 
124
+ end
128
125
 
129
126
  class Gruff::Layer
130
-
127
+
131
128
  attr_reader :name
132
-
129
+
133
130
  def initialize(base_dir, folder_name)
134
131
  @base_dir = base_dir.to_s
135
132
  @name = folder_name.to_s
136
133
  @filenames = Dir.open(File.join(base_dir, folder_name)).entries.select { |file| file =~ /^[^.]+\.png$/ }.sort
137
134
  @selected_filename = select_default
138
135
  end
139
-
136
+
140
137
  # Register this layer so it receives updates from the group
141
138
  def observe(obj)
142
139
  obj.add_observer self
143
140
  end
144
-
141
+
145
142
  # Choose the appropriate filename for this layer, based on the input
146
143
  def update(value)
147
144
  @selected_filename = case value.to_s
@@ -165,6 +162,7 @@ class Gruff::Layer
165
162
  unless @selected_filename.nil? || @selected_filename.empty?
166
163
  return File.join(@base_dir, @name, @selected_filename)
167
164
  end
165
+
168
166
  ''
169
167
  end
170
168
 
@@ -179,7 +177,7 @@ private
179
177
  def select_numeric(value)
180
178
  file_exists_or_blank value.to_s.gsub('-', '_')
181
179
  end
182
-
180
+
183
181
  def select_time(value)
184
182
  times = @filenames.map { |filename| filename.gsub('.png', '') }
185
183
  times.each_with_index do |time, index|
@@ -189,12 +187,12 @@ private
189
187
  end
190
188
  return "#{times.last}.png"
191
189
  end
192
-
190
+
193
191
  # Match "partly cloudy" to "partly_cloudy.png"
194
192
  def select_string(value)
195
193
  file_exists_or_blank value.to_s.gsub(' ', '_')
196
194
  end
197
-
195
+
198
196
  def select_default
199
197
  @filenames.include?("default.png") ? "default.png" : ''
200
198
  end
@@ -205,5 +203,5 @@ private
205
203
  def file_exists_or_blank(filename)
206
204
  @filenames.include?("#{filename}.png") ? "#{filename}.png" : select_default
207
205
  end
208
-
206
+
209
207
  end
@@ -13,10 +13,11 @@ class Gruff::SideBar < Gruff::Base
13
13
  super
14
14
 
15
15
  return unless @has_data
16
+
16
17
  draw_bars
17
18
  end
18
19
 
19
- protected
20
+ protected
20
21
 
21
22
  def draw_bars
22
23
  # Setup spacing.
@@ -39,7 +40,6 @@ class Gruff::SideBar < Gruff::Base
39
40
  @d = @d.fill data_row[DATA_COLOR_INDEX]
40
41
 
41
42
  data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
42
-
43
43
  # Using the original calcs from the stacked bar chart
44
44
  # to get the difference between
45
45
  # part of the bart chart we wish to stack.
@@ -59,7 +59,7 @@ class Gruff::SideBar < Gruff::Base
59
59
  # Calculate center based on bar_width and current row
60
60
 
61
61
  if @use_data_label
62
- label_center = @graph_top + (@bar_width * (row_index+point_index) + @bar_width / 2)
62
+ label_center = @graph_top + (@bar_width * (row_index + point_index) + @bar_width / 2)
63
63
  draw_label(label_center, row_index, @norm_data[row_index][DATA_LABEL_INDEX])
64
64
  else
65
65
  label_center = @graph_top + (@bars_width * point_index + @bars_width / 2)
@@ -67,10 +67,9 @@ class Gruff::SideBar < Gruff::Base
67
67
  end
68
68
  if @show_labels_for_bar_values
69
69
  val = (@label_formatting || '%.2f') % @norm_data[row_index][3][point_index]
70
- draw_value_label(right_x+40, (@graph_top + (((row_index+point_index+1) * @bar_width) - (@bar_width / 2)))-12, val.commify, true)
70
+ draw_value_label(right_x + 40, (@graph_top + (((row_index + point_index + 1) * @bar_width) - (@bar_width / 2))) - 12, val.commify, true)
71
71
  end
72
72
  end
73
-
74
73
  end
75
74
 
76
75
  @d.draw(@base_image)
@@ -78,7 +77,6 @@ class Gruff::SideBar < Gruff::Base
78
77
 
79
78
  # Instead of base class version, draws vertical background lines and label
80
79
  def draw_line_markers
81
-
82
80
  return if @hide_line_markers
83
81
 
84
82
  @d = @d.stroke_antialias false
@@ -92,7 +90,6 @@ class Gruff::SideBar < Gruff::Base
92
90
  # TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
93
91
  increment = significant(@spread.to_f / number_of_lines)
94
92
  (0..number_of_lines).each do |index|
95
-
96
93
  line_diff = (@graph_right - @graph_left) / number_of_lines
97
94
  x = @graph_right - (line_diff * index) - 1
98
95
  @d = @d.line(x, @graph_bottom, x, @graph_top)
@@ -118,7 +115,7 @@ class Gruff::SideBar < Gruff::Base
118
115
  ##
119
116
  # Draw on the Y axis instead of the X
120
117
 
121
- def draw_label(y_offset, index, label=nil)
118
+ def draw_label(y_offset, index, label = nil)
122
119
  if !@labels[index].nil? && @labels_seen[index].nil?
123
120
  lbl = (@use_data_label) ? label : @labels[index]
124
121
  @d.fill = @font_color