gruff 0.10.0-java → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6efd63c58b0b6e99141a8f96acac661c53bf7c3c36b9821e3ff6e39846de6601
4
- data.tar.gz: f1a55c5c16668094c461de8a201e6358ce23054829687af411e6b4b343949803
3
+ metadata.gz: f2eb363f545e171df5a5d457b5d34e867a060dc4d84eda87d77b2447172d2c04
4
+ data.tar.gz: fa7708d508f2a016c11af3c08d2b877ff65eaf62955658c9b57fbd08b9f45659
5
5
  SHA512:
6
- metadata.gz: feecb5cf63e6b621b9a4b17f1b71d83f2e1ddfc1d4f09eb0efe432b767f484fdb672a1bda4712da0df628ecde9f234553c18eeb5de59f08ed3cdb196026f534e
7
- data.tar.gz: 1cf1098579f7c942cced3ab22fef432245b1708aa0a3fcfdcf6d69556c378ab0801dfcbe52060c36b77d3be4035940693f04ff919c7ee7ad904e2aca00349853
6
+ metadata.gz: 06d22482b55dd1f478f9ad8ae660f8fe96a4f4b8c7f651207b3de2d1cacf9c1399cf6d88ebd3fdad3178acb020371924f189fa86ee6107d240850788dd9156f3
7
+ data.tar.gz: 61461cbe1691e7aec5a6c178778c0f40ede97d496857f6a797867be3ae6f52565b33ad8556654ce592aec2717e11e7512bf2cfb25e7cfcdff9797da1faeb9b01
@@ -18,9 +18,6 @@ Layout/AccessModifierIndentation:
18
18
  Layout/ClassStructure:
19
19
  Enabled: false
20
20
 
21
- Layout/CommentIndentation:
22
- Enabled: false
23
-
24
21
  Layout/FirstMethodArgumentLineBreak:
25
22
  Enabled: false
26
23
 
@@ -39,6 +36,9 @@ Lint/AssignmentInCondition:
39
36
  Lint/NumberConversion:
40
37
  Enabled: false
41
38
 
39
+ Style/ClassAndModuleChildren:
40
+ Enabled: false
41
+
42
42
  Style/ConditionalAssignment:
43
43
  Enabled: false
44
44
 
@@ -41,7 +41,7 @@ Metrics/BlockLength:
41
41
  # Offense count: 12
42
42
  # Configuration parameters: CountComments.
43
43
  Metrics/ClassLength:
44
- Max: 634
44
+ Max: 637
45
45
 
46
46
  # Offense count: 12
47
47
  # Configuration parameters: IgnoredMethods.
@@ -85,24 +85,6 @@ Security/Eval:
85
85
  Exclude:
86
86
  - 'test/gruff_test_case.rb'
87
87
 
88
- # Offense count: 1
89
- # Cop supports --auto-correct.
90
- # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
91
- # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
92
- # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
93
- # FunctionalMethods: let, let!, subject, watch
94
- # IgnoredMethods: lambda, proc, it
95
- Style/BlockDelimiters:
96
- Exclude:
97
- - 'test/test_accumulator_bar.rb'
98
-
99
- # Offense count: 33
100
- # Cop supports --auto-correct.
101
- # Configuration parameters: AutoCorrect, EnforcedStyle.
102
- # SupportedStyles: nested, compact
103
- Style/ClassAndModuleChildren:
104
- Enabled: false
105
-
106
88
  # Offense count: 39
107
89
  Style/Documentation:
108
90
  Enabled: false
@@ -1,5 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.11.0
4
+ - Fix regression in empty data handling (#445)
5
+ - Rendering text in front most (#439)
6
+ - Allow to change settings even after entered the data in Gruff::Histogram (#437)
7
+ - Adjust label position in Gruff::Net (#436)
8
+ - Adjust LABEL_MARGIN value (#435)
9
+ - Add shadow line in marker line into Gruff::{Dot, SideBar, Scatter} (#430)
10
+ - Move no data message to the vertical center (#428)
11
+ - Remove the getter method in attributes for configuration (#424)
12
+ - Fix title margin in Gruff::Bullet if empty title was given (#422)
13
+
3
14
  ## 0.10.0
4
15
 
5
16
  * Add Histogram chart (#419)
data/Rakefile CHANGED
@@ -20,4 +20,28 @@ namespace :test do
20
20
  system "ruby #{file}"
21
21
  end
22
22
  end
23
+
24
+ desc 'Update expected image with output'
25
+ task :"image:update" do
26
+ require 'rmagick'
27
+ require 'fileutils'
28
+
29
+ update_expected_images = lambda do |expect_dir, output_dir|
30
+ Dir.glob("#{output_dir}/*.png") do |output_path|
31
+ file_name = File.basename(output_path)
32
+ expected_path = "#{expect_dir}/#{file_name}"
33
+
34
+ expected_image = Magick::Image.read(expected_path).first
35
+ output_image = Magick::Image.read(output_path).first
36
+ _, error = expected_image.compare_channel(output_image, Magick::PeakAbsoluteErrorMetric)
37
+
38
+ if error != 0.0
39
+ FileUtils.copy(output_path, expected_path)
40
+ end
41
+ end
42
+ end
43
+
44
+ update_expected_images.call('test/expected', 'test/output')
45
+ update_expected_images.call('test/expected_java', 'test/output_java')
46
+ end
23
47
  end
@@ -17,10 +17,10 @@ require 'gruff/base'
17
17
  #
18
18
  class Gruff::Area < Gruff::Base
19
19
  # Specifies the filling opacity in area graph. Default is +0.85+.
20
- attr_accessor :fill_opacity
20
+ attr_writer :fill_opacity
21
21
 
22
22
  # Specifies the stroke width in line around area graph. Default is +2.0+.
23
- attr_accessor :stroke_width
23
+ attr_writer :stroke_width
24
24
 
25
25
  def initialize_ivars
26
26
  super
@@ -20,22 +20,23 @@ require 'gruff/helper/bar_conversion'
20
20
  #
21
21
  class Gruff::Bar < Gruff::Base
22
22
  # Spacing factor applied between bars.
23
- attr_accessor :bar_spacing
23
+ attr_writer :bar_spacing
24
24
 
25
25
  # Spacing factor applied between a group of bars belonging to the same label.
26
- attr_accessor :group_spacing
26
+ attr_writer :group_spacing
27
27
 
28
28
  # Set the number output format for labels using sprintf.
29
29
  # Default is +"%.2f"+.
30
- attr_accessor :label_formatting
30
+ attr_writer :label_formatting
31
31
 
32
32
  # Output the values for the bars on a bar graph.
33
33
  # Default is +false+.
34
- attr_accessor :show_labels_for_bar_values
34
+ attr_writer :show_labels_for_bar_values
35
35
 
36
36
  def initialize_ivars
37
37
  super
38
38
  @spacing_factor = 0.9
39
+ @group_spacing = 10
39
40
  @label_formatting = nil
40
41
  @show_labels_for_bar_values = false
41
42
  end
@@ -72,7 +73,6 @@ protected
72
73
  #
73
74
  # Columns sit side-by-side.
74
75
  @bar_spacing ||= @spacing_factor # space between the bars
75
- @group_spacing ||= 10
76
76
 
77
77
  bar_width = (@graph_width - calculate_spacing) / (column_count * store.length).to_f
78
78
  padding = (bar_width * (1 - @bar_spacing)) / 2
@@ -20,28 +20,28 @@ module Gruff
20
20
  class Base
21
21
  # Space around text elements. Mostly used for vertical spacing.
22
22
  LEGEND_MARGIN = TITLE_MARGIN = 20.0
23
- LABEL_MARGIN = 10.0
23
+ LABEL_MARGIN = 15.0
24
24
  DEFAULT_MARGIN = 20.0
25
25
 
26
26
  DEFAULT_TARGET_WIDTH = 800.0
27
27
 
28
28
  # Blank space above the graph. Default is +20+.
29
- attr_accessor :top_margin
29
+ attr_writer :top_margin
30
30
 
31
31
  # Blank space below the graph. Default is +20+.
32
- attr_accessor :bottom_margin
32
+ attr_writer :bottom_margin
33
33
 
34
34
  # Blank space to the right of the graph. Default is +20+.
35
- attr_accessor :right_margin
35
+ attr_writer :right_margin
36
36
 
37
37
  # Blank space to the left of the graph. Default is +20+.
38
- attr_accessor :left_margin
38
+ attr_writer :left_margin
39
39
 
40
40
  # Blank space below the title. Default is +20+.
41
- attr_accessor :title_margin
41
+ attr_writer :title_margin
42
42
 
43
43
  # Blank space below the legend. Default is +20+.
44
- attr_accessor :legend_margin
44
+ attr_writer :legend_margin
45
45
 
46
46
  # A hash of names for the individual columns, where the key is the array
47
47
  # index for the column this label represents.
@@ -50,118 +50,113 @@ module Gruff
50
50
  #
51
51
  # @example
52
52
  # { 0 => 2005, 3 => 2006, 5 => 2007, 7 => 2008 }
53
- attr_accessor :labels
53
+ attr_writer :labels
54
54
 
55
55
  # Used internally for spacing.
56
56
  #
57
57
  # By default, labels are centered over the point they represent.
58
- attr_accessor :center_labels_over_point
58
+ attr_writer :center_labels_over_point
59
59
 
60
60
  # Used internally for horizontal graph types. Default is +false+.
61
- attr_accessor :has_left_labels
61
+ attr_writer :has_left_labels
62
62
 
63
63
  # Set a label for the bottom of the graph.
64
- attr_accessor :x_axis_label
64
+ attr_writer :x_axis_label
65
65
 
66
66
  # Set a label for the left side of the graph.
67
- attr_accessor :y_axis_label
67
+ attr_writer :y_axis_label
68
68
 
69
69
  # Set increment of the vertical marking lines.
70
- attr_accessor :x_axis_increment
70
+ attr_writer :x_axis_increment
71
71
 
72
72
  # Set increment of the horizontal marking lines.
73
- attr_accessor :y_axis_increment
73
+ attr_writer :y_axis_increment
74
74
 
75
75
  # Height of staggering between labels (Bar graph only).
76
- attr_accessor :label_stagger_height
76
+ attr_writer :label_stagger_height
77
77
 
78
78
  # Truncates labels if longer than max specified.
79
- attr_accessor :label_max_size
79
+ attr_writer :label_max_size
80
80
 
81
- # How truncated labels visually appear if they exceed {#label_max_size}.
81
+ # How truncated labels visually appear if they exceed {#label_max_size=}.
82
82
  #
83
83
  # - +:absolute+ - does not show trailing dots to indicate truncation. This is the default.
84
- # - +:trailing_dots+ - shows trailing dots to indicate truncation (note that {#label_max_size}
84
+ # - +:trailing_dots+ - shows trailing dots to indicate truncation (note that {#label_max_size=}
85
85
  # must be greater than 3).
86
- attr_accessor :label_truncation_style
86
+ attr_writer :label_truncation_style
87
87
 
88
88
  # Get or set the list of colors that will be used to draw the bars or lines.
89
89
  attr_accessor :colors
90
90
 
91
91
  # Set the large title of the graph displayed at the top.
92
- attr_accessor :title
92
+ attr_writer :title
93
93
 
94
- # Font used for titles, labels, etc. Works best if you provide the full
95
- # path to the TTF font file. RMagick must be built with the Freetype
96
- # libraries for this to work properly.
97
- attr_reader :font
98
-
99
- # Same as {#font} but for the title.
100
- attr_accessor :title_font
94
+ # Same as {#font=} but for the title.
95
+ attr_writer :title_font
101
96
 
102
97
  # Specifies whether to draw the title bolded or not. Default is +true+.
103
- attr_accessor :bold_title
98
+ attr_writer :bold_title
104
99
 
105
100
  # Specifies the text color.
106
- attr_accessor :font_color
101
+ attr_writer :font_color
107
102
 
108
103
  # Prevent drawing of line markers. Default is +false+.
109
- attr_accessor :hide_line_markers
104
+ attr_writer :hide_line_markers
110
105
 
111
106
  # Prevent drawing of the legend. Default is +false+.
112
- attr_accessor :hide_legend
107
+ attr_writer :hide_legend
113
108
 
114
109
  # Prevent drawing of the title. Default is +false+.
115
- attr_accessor :hide_title
110
+ attr_writer :hide_title
116
111
 
117
112
  # Prevent drawing of line numbers. Default is +false+.
118
- attr_accessor :hide_line_numbers
113
+ attr_writer :hide_line_numbers
119
114
 
120
115
  # Set a message shown when there is no data. Fits up to 20 characters. Defaults
121
116
  # to +"No Data."+.
122
- attr_accessor :no_data_message
117
+ attr_writer :no_data_message
123
118
 
124
119
  # Set the font size of the large title at the top of the graph. Default is +36+.
125
- attr_accessor :title_font_size
120
+ attr_writer :title_font_size
126
121
 
127
122
  # Optionally set the size of the font. Based on an 800x600px graph.
128
123
  # Default is +20+.
129
124
  #
130
125
  # Will be scaled down if the graph is smaller than 800px wide.
131
- attr_accessor :legend_font_size
126
+ attr_writer :legend_font_size
132
127
 
133
128
  # Display the legend under the graph. Default is +false+.
134
- attr_accessor :legend_at_bottom
129
+ attr_writer :legend_at_bottom
135
130
 
136
131
  # The font size of the labels around the graph. Default is +21+.
137
- attr_accessor :marker_font_size
132
+ attr_writer :marker_font_size
138
133
 
139
134
  # Set the color of the auxiliary lines.
140
- attr_accessor :marker_color
135
+ attr_writer :marker_color
141
136
 
142
137
  # Set the shadow color of the auxiliary lines.
143
- attr_accessor :marker_shadow_color
138
+ attr_writer :marker_shadow_color
144
139
 
145
140
  # Set the number of horizontal lines shown for reference.
146
- attr_accessor :marker_count
141
+ attr_writer :marker_count
147
142
 
148
143
  # Set to +true+ if you want the data sets sorted with largest avg values drawn
149
144
  # first. Default is +false+.
150
- attr_accessor :sort
145
+ attr_writer :sort
151
146
 
152
147
  # Set to +true+ if you want the data sets drawn with largest avg values drawn
153
148
  # first. This does not affect the legend. Default is +false+.
154
- attr_accessor :sorted_drawing
149
+ attr_writer :sorted_drawing
155
150
 
156
151
  # Optionally set the size of the colored box by each item in the legend.
157
152
  # Default is +20.0+.
158
153
  #
159
154
  # Will be scaled down if graph is smaller than 800px wide.
160
- attr_accessor :legend_box_size
155
+ attr_writer :legend_box_size
161
156
 
162
157
  # With Side Bars use the data label for the marker value to the left of the bar.
163
158
  # Default is +false+.
164
- attr_accessor :use_data_label
159
+ attr_writer :use_data_label
165
160
 
166
161
  # If one numerical argument is given, the graph is drawn at 4/3 ratio
167
162
  # according to the given width (+800+ results in 800x600, +400+ gives 400x300,
@@ -173,9 +168,7 @@ module Gruff
173
168
  #
174
169
  def initialize(target_width = DEFAULT_TARGET_WIDTH)
175
170
  if target_width.is_a?(String)
176
- geometric_width, geometric_height = target_width.split('x')
177
- @columns = geometric_width.to_f
178
- @rows = geometric_height.to_f
171
+ @columns, @rows = target_width.split('x').map(&:to_f)
179
172
  else
180
173
  @columns = target_width.to_f
181
174
  @rows = target_width.to_f * 0.75
@@ -183,19 +176,14 @@ module Gruff
183
176
  @columns.freeze
184
177
  @rows.freeze
185
178
 
179
+ initialize_graph_scale
186
180
  initialize_ivars
181
+ initialize_store
187
182
 
188
183
  self.theme = Themes::KEYNOTE
189
184
  end
190
185
 
191
- # Set instance variables for this object.
192
- #
193
- # Subclasses can override this, call super, then set values separately.
194
- #
195
- # This makes it possible to set defaults in a subclass but still allow
196
- # developers to change this values in their program.
197
- def initialize_ivars
198
- # Internal for calculations
186
+ def initialize_graph_scale
199
187
  @raw_columns = DEFAULT_TARGET_WIDTH
200
188
  @raw_rows = DEFAULT_TARGET_WIDTH * (@rows / @columns)
201
189
  @raw_columns.freeze
@@ -203,10 +191,23 @@ module Gruff
203
191
 
204
192
  @scale = @columns / @raw_columns
205
193
  @scale.freeze
194
+ end
195
+ protected :initialize_graph_scale
196
+
197
+ def initialize_store
198
+ @store = Gruff::Store.new(Gruff::Store::BaseData)
199
+ end
200
+ protected :initialize_store
206
201
 
202
+ # Initialize instance variable of attribures
203
+ #
204
+ # Subclasses can override this, call super, then set values separately.
205
+ #
206
+ # This makes it possible to set defaults in a subclass but still allow
207
+ # developers to change this values in their program.
208
+ def initialize_ivars
207
209
  @marker_count = nil
208
210
  @maximum_value = @minimum_value = nil
209
- @increment = nil
210
211
  @labels = {}
211
212
  @sort = false
212
213
  @sorted_drawing = false
@@ -235,14 +236,10 @@ module Gruff
235
236
  @label_max_size = 0
236
237
  @label_truncation_style = :absolute
237
238
 
238
- @theme_options = {}
239
-
240
239
  @use_data_label = false
241
240
  @x_axis_increment = nil
242
241
  @x_axis_label = @y_axis_label = nil
243
242
  @y_axis_increment = nil
244
-
245
- @store = Gruff::Store.new(Gruff::Store::BaseData)
246
243
  end
247
244
  protected :initialize_ivars
248
245
 
@@ -298,11 +295,20 @@ module Gruff
298
295
  # graph.theme = {
299
296
  # colors: %w(orange purple green white red),
300
297
  # marker_color: 'blue',
301
- # background_colors: ['black', 'grey', :top_bottom]
298
+ # background_colors: ['black', 'grey'],
299
+ # background_direction: :top_bottom
302
300
  # }
303
301
  #
304
302
  # +background_image: 'squirrel.png'+ is also possible.
305
303
  #
304
+ # +background_direction+ accepts one of following parameters.
305
+ # - +:top_bottom+
306
+ # - +:bottom_top+
307
+ # - +:left_right+
308
+ # - +:right_left+
309
+ # - +:topleft_bottomright+
310
+ # - +:topright_bottomleft+
311
+ #
306
312
  # (Or hopefully something better looking than that.)
307
313
  #
308
314
  # @param options [Hash] The optional setting for theme
@@ -413,9 +419,11 @@ module Gruff
413
419
  end
414
420
 
415
421
  # Return the graph as a rendered binary blob.
416
- def to_blob(file_format = 'PNG')
422
+ #
423
+ # @param image_format [String] The image format of binary blob.
424
+ def to_blob(image_format = 'PNG')
417
425
  draw
418
- Gruff::Renderer.to_blob(file_format)
426
+ Gruff::Renderer.to_blob(image_format)
419
427
  end
420
428
 
421
429
  protected
@@ -496,57 +504,17 @@ module Gruff
496
504
  # Calculates size of drawable area, general font dimensions, etc.
497
505
 
498
506
  def setup_graph_measurements
499
- @marker_caps_height = @hide_line_markers ? 0 : calculate_caps_height(@marker_font_size)
500
- @title_caps_height = hide_title? ? 0 : calculate_caps_height(@title_font_size) * @title.lines.to_a.size
501
- @legend_caps_height = @hide_legend ? 0 : calculate_caps_height(@legend_font_size)
502
-
503
- if @hide_line_markers
504
- @graph_left = @left_margin
505
- @graph_right_margin = @right_margin
506
- @graph_bottom_margin = @bottom_margin
507
- else
508
- if @has_left_labels
509
- longest_left_label_width = calculate_width(@marker_font_size,
510
- labels.values.reduce('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
511
- else
512
- longest_left_label_width = calculate_width(@marker_font_size,
513
- label(maximum_value.to_f, @increment))
514
- end
515
-
516
- # Shift graph if left line numbers are hidden
517
- line_number_width = @hide_line_numbers && !@has_left_labels ? 0.0 : (longest_left_label_width + LABEL_MARGIN * 2)
518
-
519
- @graph_left = @left_margin + line_number_width + (@y_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN * 2)
520
-
521
- # Make space for half the width of the rightmost column label.
522
- # Might be greater than the number of columns if between-style bar markers are used.
523
- last_label = @labels.keys.max.to_i
524
- extra_room_for_long_label = begin
525
- (last_label >= (column_count - 1) && @center_labels_over_point) ? calculate_width(@marker_font_size, @labels[last_label]) / 2.0 : 0
526
- end
527
- @graph_right_margin = @right_margin + extra_room_for_long_label
528
-
529
- @graph_bottom_margin = @bottom_margin + @marker_caps_height + LABEL_MARGIN
530
- end
531
-
532
- @graph_right = @raw_columns - @graph_right_margin
533
- @graph_width = @raw_columns - @graph_left - @graph_right_margin
507
+ @marker_caps_height = setup_marker_caps_height
508
+ @title_caps_height = setup_title_caps_height
509
+ @legend_caps_height = setup_legend_caps_height
534
510
 
535
- # When @hide title, leave a title_margin space for aesthetics.
536
- # Same with @hide_legend
537
- @graph_top = begin
538
- if @legend_at_bottom
539
- @top_margin
540
- else
541
- @top_margin +
542
- (hide_title? ? title_margin : @title_caps_height + title_margin) +
543
- (@hide_legend ? legend_margin : @legend_caps_height + legend_margin)
544
- end
545
- end
511
+ margin_on_right = graph_right_margin
512
+ @graph_right = @raw_columns - margin_on_right
513
+ @graph_left = setup_left_margin
514
+ @graph_top = setup_top_margin
515
+ @graph_bottom = setup_bottom_margin
546
516
 
547
- x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN
548
- # FIXME: Consider chart types other than bar
549
- @graph_bottom = @raw_rows - @graph_bottom_margin - x_axis_label_height - @label_stagger_height
517
+ @graph_width = @raw_columns - @graph_left - margin_on_right
550
518
  @graph_height = @graph_bottom - @graph_top
551
519
  end
552
520
 
@@ -556,17 +524,17 @@ module Gruff
556
524
  # X Axis
557
525
  # Centered vertically and horizontally by setting the
558
526
  # height to 1.0 and the width to the width of the graph.
559
- x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN * 2 + @marker_caps_height
527
+ x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN + @marker_caps_height
560
528
 
561
529
  # TODO: Center between graph area
562
530
  text_renderer = Gruff::Renderer::Text.new(@x_axis_label, font: @font, size: @marker_font_size, color: @font_color)
563
- text_renderer.render(@raw_columns, 1.0, 0.0, x_axis_label_y_coordinate)
531
+ text_renderer.add_to_render_queue(@raw_columns, 1.0, 0.0, x_axis_label_y_coordinate)
564
532
  end
565
533
 
566
534
  if @y_axis_label
567
535
  # Y Axis, rotated vertically
568
536
  text_renderer = Gruff::Renderer::Text.new(@y_axis_label, font: @font, size: @marker_font_size, color: @font_color, rotation: -90)
569
- text_renderer.render(1.0, @raw_rows, @left_margin + @marker_caps_height / 2.0, 0.0, Magick::CenterGravity)
537
+ text_renderer.add_to_render_queue(1.0, @raw_rows, @left_margin + @marker_caps_height / 2.0, 0.0, Magick::CenterGravity)
570
538
  end
571
539
  end
572
540
 
@@ -580,17 +548,14 @@ module Gruff
580
548
  (0..@marker_count).each do |index|
581
549
  y = @graph_top + @graph_height - index.to_f * increment_scaled
582
550
 
583
- Gruff::Renderer::Line.new(color: @marker_color).render(@graph_left, y, @graph_right, y)
584
- #If the user specified a marker shadow color, draw a shadow just below it
585
- if @marker_shadow_color
586
- Gruff::Renderer::Line.new(color: @marker_shadow_color).render(@graph_left, y + 1, @graph_right, y + 1)
587
- end
551
+ line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
552
+ line_renderer.render(@graph_left, y, @graph_right, y)
588
553
 
589
554
  unless @hide_line_numbers
590
555
  marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
591
556
  label = label(marker_label, @increment)
592
557
  text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color)
593
- text_renderer.render(@graph_left - LABEL_MARGIN, 1.0, 0.0, y, Magick::EastGravity)
558
+ text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y, Magick::EastGravity)
594
559
  end
595
560
  end
596
561
  end
@@ -613,27 +578,15 @@ module Gruff
613
578
  return if @hide_legend
614
579
 
615
580
  legend_labels = store.data.map(&:label)
616
-
617
581
  legend_square_width = @legend_box_size # small square with color of this item
618
-
619
- # May fix legend drawing problem at small sizes
620
- label_widths = [[]] # Used to calculate line wrap
621
- legend_labels.each do |label|
622
- width = calculate_width(@legend_font_size, label)
623
- label_width = width + legend_square_width * 2.7
624
- label_widths.last.push label_width
625
-
626
- if sum(label_widths.last) > (@raw_columns * 0.9)
627
- label_widths.push [label_widths.last.pop]
628
- end
629
- end
582
+ label_widths = calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
630
583
 
631
584
  current_x_offset = center(sum(label_widths.first))
632
585
  current_y_offset = begin
633
586
  if @legend_at_bottom
634
- @graph_height + title_margin
587
+ @graph_height + @title_margin
635
588
  else
636
- hide_title? ? @top_margin + title_margin : @top_margin + title_margin + @title_caps_height
589
+ hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + @title_caps_height
637
590
  end
638
591
  end
639
592
 
@@ -642,7 +595,7 @@ module Gruff
642
595
 
643
596
  # Draw label
644
597
  text_renderer = Gruff::Renderer::Text.new(legend_label, font: @font, size: @legend_font_size, color: @font_color)
645
- text_renderer.render(@raw_columns, 1.0, current_x_offset + (legend_square_width * 1.7), current_y_offset, Magick::WestGravity)
598
+ text_renderer.add_to_render_queue(@raw_columns, 1.0, current_x_offset + (legend_square_width * 1.7), current_y_offset, Magick::WestGravity)
646
599
 
647
600
  # Now draw box with color of this dataset
648
601
  rect_renderer = Gruff::Renderer::Rectangle.new(color: store.data[index].color)
@@ -651,23 +604,21 @@ module Gruff
651
604
  current_x_offset + legend_square_width,
652
605
  current_y_offset + legend_square_width / 2.0)
653
606
 
654
- width = calculate_width(legend_font_size, legend_label)
655
- current_string_offset = width + (legend_square_width * 2.7)
607
+ width = calculate_width(@legend_font_size, legend_label)
608
+ current_x_offset += width + (legend_square_width * 2.7)
609
+ label_widths.first.shift
656
610
 
657
611
  # Handle wrapping
658
- label_widths.first.shift
659
612
  if label_widths.first.empty?
660
613
  label_widths.shift
661
614
  current_x_offset = center(sum(label_widths.first)) unless label_widths.empty?
662
- line_height = [@legend_caps_height, legend_square_width].max + legend_margin
615
+ line_height = [@legend_caps_height, legend_square_width].max + @legend_margin
663
616
  unless label_widths.empty?
664
617
  # Wrap to next line and shrink available graph dimensions
665
618
  current_y_offset += line_height
666
619
  @graph_top += line_height
667
620
  @graph_height = @graph_bottom - @graph_top
668
621
  end
669
- else
670
- current_x_offset += current_string_offset
671
622
  end
672
623
  end
673
624
  end
@@ -685,7 +636,7 @@ module Gruff
685
636
  font_size = font_size * (@raw_columns / metrics.width) * 0.95
686
637
  end
687
638
  text_renderer = Gruff::Renderer::Text.new(@title, font: font, size: font_size, color: @font_color, weight: font_weight)
688
- text_renderer.render(@raw_columns, 1.0, 0, @top_margin)
639
+ text_renderer.add_to_render_queue(@raw_columns, 1.0, 0, @top_margin)
689
640
  end
690
641
 
691
642
  # Draws column labels below graph, centered over x_offset
@@ -700,11 +651,11 @@ module Gruff
700
651
  # TODO: See if index.odd? is the best stragegy
701
652
  y_offset += @label_stagger_height if index.odd?
702
653
 
703
- label_text = truncate_label_text(labels[index].to_s)
654
+ label_text = truncate_label_text(@labels[index].to_s)
704
655
 
705
656
  if x_offset >= @graph_left && x_offset <= @graph_right
706
657
  text_renderer = Gruff::Renderer::Text.new(label_text, font: @font, size: @marker_font_size, color: @font_color)
707
- text_renderer.render(1.0, 1.0, x_offset, y_offset, gravity)
658
+ text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset, gravity)
708
659
  end
709
660
  end
710
661
  end
@@ -724,13 +675,13 @@ module Gruff
724
675
  return if @hide_line_markers && !bar_value
725
676
 
726
677
  text_renderer = Gruff::Renderer::Text.new(data_point, font: @font, size: @marker_font_size, color: @font_color)
727
- text_renderer.render(1.0, 1.0, x_offset, y_offset)
678
+ text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
728
679
  end
729
680
 
730
681
  # Shows an error message because you have no data.
731
682
  def draw_no_data
732
683
  text_renderer = Gruff::Renderer::Text.new(@no_data_message, font: @font, size: 80, color: @font_color)
733
- text_renderer.render(@raw_columns, @raw_rows / 2.0, 0, 10, Magick::CenterGravity)
684
+ text_renderer.render(@raw_columns, @raw_rows, 0, 0, Magick::CenterGravity)
734
685
  end
735
686
 
736
687
  # Resets everything to defaults (except data).
@@ -794,6 +745,63 @@ module Gruff
794
745
 
795
746
  private
796
747
 
748
+ def setup_marker_caps_height
749
+ @hide_line_markers ? 0 : calculate_caps_height(@marker_font_size)
750
+ end
751
+
752
+ def setup_title_caps_height
753
+ hide_title? ? 0 : calculate_caps_height(@title_font_size) * @title.lines.to_a.size
754
+ end
755
+
756
+ def setup_legend_caps_height
757
+ @hide_legend ? 0 : calculate_caps_height(@legend_font_size)
758
+ end
759
+
760
+ def graph_right_margin
761
+ @hide_line_markers ? @right_margin : @right_margin + extra_room_for_long_label
762
+ end
763
+
764
+ def extra_room_for_long_label
765
+ # Make space for half the width of the rightmost column label.
766
+ # Might be greater than the number of columns if between-style bar markers are used.
767
+ last_label = @labels.keys.max.to_i
768
+ (last_label >= (column_count - 1) && @center_labels_over_point) ? calculate_width(@marker_font_size, @labels[last_label]) / 2.0 : 0
769
+ end
770
+
771
+ def setup_left_margin
772
+ return @left_margin if @hide_line_markers
773
+
774
+ if @has_left_labels
775
+ longest_left_label_width = calculate_width(@marker_font_size,
776
+ @labels.values.reduce('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
777
+ else
778
+ longest_left_label_width = calculate_width(@marker_font_size,
779
+ label(maximum_value.to_f, @increment))
780
+ end
781
+ # Shift graph if left line numbers are hidden
782
+ line_number_width = @hide_line_numbers && !@has_left_labels ? 0.0 : (longest_left_label_width + LABEL_MARGIN * 2)
783
+
784
+ @left_margin + line_number_width + (@y_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN * 2)
785
+ end
786
+
787
+ def setup_top_margin
788
+ return @top_margin if @legend_at_bottom
789
+
790
+ # When @hide title, leave a title_margin space for aesthetics.
791
+ # Same with @hide_legend
792
+ @top_margin +
793
+ (hide_title? ? @title_margin : @title_caps_height + @title_margin) +
794
+ (@hide_legend ? @legend_margin : @legend_caps_height + @legend_margin)
795
+ end
796
+
797
+ def setup_bottom_margin
798
+ graph_bottom_margin = @hide_line_markers ? @bottom_margin : @bottom_margin + @marker_caps_height + LABEL_MARGIN
799
+
800
+ x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN
801
+ # FIXME: Consider chart types other than bar
802
+ @raw_rows - graph_bottom_margin - x_axis_label_height - @label_stagger_height
803
+ end
804
+
797
805
  def truncate_label_text(text)
798
806
  return text if text.size <= @label_max_size
799
807
 
@@ -838,6 +846,22 @@ module Gruff
838
846
  parts.join('.')
839
847
  end
840
848
 
849
+ def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
850
+ # May fix legend drawing problem at small sizes
851
+ label_widths = [[]] # Used to calculate line wrap
852
+ legend_labels.each do |label|
853
+ width = calculate_width(@legend_font_size, label)
854
+ label_width = width + legend_square_width * 2.7
855
+ label_widths.last.push label_width
856
+
857
+ if sum(label_widths.last) > (@raw_columns * 0.9)
858
+ label_widths.push [label_widths.last.pop]
859
+ end
860
+ end
861
+
862
+ label_widths
863
+ end
864
+
841
865
  # Returns the height of the capital letter 'X' for the current font and
842
866
  # size.
843
867
  #