gruff 0.12.2 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +66 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +34 -27
- data/CHANGELOG.md +29 -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 +9 -10
- data/lib/gruff/accumulator_bar.rb +3 -1
- data/lib/gruff/area.rb +5 -8
- data/lib/gruff/bar.rb +32 -49
- data/lib/gruff/base.rb +199 -115
- data/lib/gruff/bezier.rb +4 -6
- data/lib/gruff/bullet.rb +12 -11
- data/lib/gruff/dot.rb +13 -14
- data/lib/gruff/font.rb +39 -0
- data/lib/gruff/helper/bar_conversion.rb +27 -12
- data/lib/gruff/helper/bar_value_label.rb +71 -0
- data/lib/gruff/helper/stacked_mixin.rb +1 -2
- data/lib/gruff/histogram.rb +9 -7
- data/lib/gruff/line.rb +57 -50
- data/lib/gruff/mini/bar.rb +9 -6
- data/lib/gruff/mini/legend.rb +12 -8
- data/lib/gruff/mini/pie.rb +9 -6
- data/lib/gruff/mini/side_bar.rb +9 -6
- data/lib/gruff/net.rb +9 -15
- data/lib/gruff/patch/rmagick.rb +0 -1
- data/lib/gruff/patch/string.rb +1 -1
- data/lib/gruff/pie.rb +23 -65
- data/lib/gruff/renderer/bezier.rb +8 -9
- data/lib/gruff/renderer/circle.rb +8 -9
- data/lib/gruff/renderer/dash_line.rb +9 -10
- data/lib/gruff/renderer/dot.rb +13 -14
- data/lib/gruff/renderer/ellipse.rb +8 -9
- data/lib/gruff/renderer/line.rb +8 -9
- data/lib/gruff/renderer/polygon.rb +9 -10
- data/lib/gruff/renderer/polyline.rb +8 -9
- data/lib/gruff/renderer/rectangle.rb +7 -8
- data/lib/gruff/renderer/renderer.rb +25 -40
- data/lib/gruff/renderer/text.rb +21 -29
- data/lib/gruff/scatter.rb +55 -75
- data/lib/gruff/scene.rb +28 -18
- data/lib/gruff/side_bar.rb +35 -54
- data/lib/gruff/side_stacked_bar.rb +14 -17
- data/lib/gruff/spider.rb +11 -20
- data/lib/gruff/stacked_area.rb +10 -11
- data/lib/gruff/stacked_bar.rb +14 -15
- data/lib/gruff/store/store.rb +6 -10
- data/lib/gruff/store/xy_data.rb +2 -0
- data/lib/gruff/themes.rb +6 -6
- data/lib/gruff/version.rb +1 -1
- data/lib/gruff.rb +68 -55
- data/rails_generators/gruff/templates/controller.rb +1 -1
- metadata +34 -20
- data/.rubocop_todo.yml +0 -190
- data/.travis.yml +0 -23
- data/assets/plastik/blue.png +0 -0
- data/assets/plastik/green.png +0 -0
- data/assets/plastik/red.png +0 -0
- data/lib/gruff/helper/bar_value_label_mixin.rb +0 -33
- data/lib/gruff/photo_bar.rb +0 -93
data/lib/gruff/base.rb
CHANGED
@@ -93,15 +93,6 @@ module Gruff
|
|
93
93
|
# Set the large title of the graph displayed at the top.
|
94
94
|
attr_writer :title
|
95
95
|
|
96
|
-
# Same as {#font=} but for the title.
|
97
|
-
attr_writer :title_font
|
98
|
-
|
99
|
-
# Specifies whether to draw the title bolded or not. Default is +true+.
|
100
|
-
attr_writer :bold_title
|
101
|
-
|
102
|
-
# Specifies the text color.
|
103
|
-
attr_writer :font_color
|
104
|
-
|
105
96
|
# Prevent drawing of line markers. Default is +false+.
|
106
97
|
attr_writer :hide_line_markers
|
107
98
|
|
@@ -118,21 +109,9 @@ module Gruff
|
|
118
109
|
# to +"No Data."+.
|
119
110
|
attr_writer :no_data_message
|
120
111
|
|
121
|
-
# Set the font size of the large title at the top of the graph. Default is +36+.
|
122
|
-
attr_writer :title_font_size
|
123
|
-
|
124
|
-
# Optionally set the size of the font. Based on an 800x600px graph.
|
125
|
-
# Default is +20+.
|
126
|
-
#
|
127
|
-
# Will be scaled down if the graph is smaller than 800px wide.
|
128
|
-
attr_writer :legend_font_size
|
129
|
-
|
130
112
|
# Display the legend under the graph. Default is +false+.
|
131
113
|
attr_writer :legend_at_bottom
|
132
114
|
|
133
|
-
# The font size of the labels around the graph. Default is +21+.
|
134
|
-
attr_writer :marker_font_size
|
135
|
-
|
136
115
|
# Set the color of the auxiliary lines.
|
137
116
|
attr_writer :marker_color
|
138
117
|
|
@@ -156,9 +135,11 @@ module Gruff
|
|
156
135
|
# Will be scaled down if graph is smaller than 800px wide.
|
157
136
|
attr_writer :legend_box_size
|
158
137
|
|
159
|
-
#
|
160
|
-
|
161
|
-
|
138
|
+
# Allow passing lambdas to format labels for x axis.
|
139
|
+
attr_writer :x_axis_label_format
|
140
|
+
|
141
|
+
# Allow passing lambdas to format labels for y axis.
|
142
|
+
attr_writer :y_axis_label_format
|
162
143
|
|
163
144
|
# If one numerical argument is given, the graph is drawn at 4/3 ratio
|
164
145
|
# according to the given width (+800+ results in 800x600, +400+ gives 400x300,
|
@@ -179,7 +160,7 @@ module Gruff
|
|
179
160
|
@rows.freeze
|
180
161
|
|
181
162
|
initialize_graph_scale
|
182
|
-
|
163
|
+
initialize_attributes
|
183
164
|
initialize_store
|
184
165
|
|
185
166
|
self.theme = Themes::KEYNOTE
|
@@ -207,21 +188,17 @@ module Gruff
|
|
207
188
|
#
|
208
189
|
# This makes it possible to set defaults in a subclass but still allow
|
209
190
|
# developers to change this values in their program.
|
210
|
-
def
|
191
|
+
def initialize_attributes
|
211
192
|
@marker_count = nil
|
212
193
|
@maximum_value = @minimum_value = nil
|
213
194
|
@labels = {}
|
214
195
|
@sort = false
|
215
196
|
@sorted_drawing = false
|
216
197
|
@title = nil
|
217
|
-
@title_font = nil
|
218
|
-
|
219
|
-
@font = nil
|
220
|
-
@bold_title = true
|
221
198
|
|
222
|
-
@
|
223
|
-
@
|
224
|
-
@
|
199
|
+
@title_font = Gruff::Font.new(size: 36.0, bold: true)
|
200
|
+
@marker_font = Gruff::Font.new(size: 21.0)
|
201
|
+
@legend_font = Gruff::Font.new(size: 20.0)
|
225
202
|
|
226
203
|
@top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
|
227
204
|
@legend_margin = LEGEND_MARGIN
|
@@ -238,12 +215,14 @@ module Gruff
|
|
238
215
|
@label_max_size = 0
|
239
216
|
@label_truncation_style = :absolute
|
240
217
|
|
241
|
-
@use_data_label = false
|
242
218
|
@x_axis_increment = nil
|
243
219
|
@x_axis_label = @y_axis_label = nil
|
244
220
|
@y_axis_increment = nil
|
221
|
+
|
222
|
+
@x_axis_label_format = nil
|
223
|
+
@y_axis_label_format = nil
|
245
224
|
end
|
246
|
-
protected :
|
225
|
+
protected :initialize_attributes
|
247
226
|
|
248
227
|
# Sets the top, bottom, left and right margins to +margin+.
|
249
228
|
#
|
@@ -258,8 +237,62 @@ module Gruff
|
|
258
237
|
# @param font_path [String] The path to font.
|
259
238
|
#
|
260
239
|
def font=(font_path)
|
261
|
-
@
|
262
|
-
|
240
|
+
@title_font.path = font_path unless @title_font.path
|
241
|
+
@marker_font.path = font_path
|
242
|
+
@legend_font.path = font_path
|
243
|
+
end
|
244
|
+
|
245
|
+
# Same as {#font=} but for the title.
|
246
|
+
#
|
247
|
+
# @param font_path [String] The path to font.
|
248
|
+
#
|
249
|
+
def title_font=(font_path)
|
250
|
+
@title_font.path = font_path
|
251
|
+
end
|
252
|
+
|
253
|
+
# Set the font size of the large title at the top of the graph. Default is +36+.
|
254
|
+
#
|
255
|
+
# @param value [Numeric] title font size
|
256
|
+
#
|
257
|
+
def title_font_size=(value)
|
258
|
+
@title_font.size = value
|
259
|
+
end
|
260
|
+
|
261
|
+
# The font size of the labels around the graph. Default is +21+.
|
262
|
+
#
|
263
|
+
# @param value [Numeric] marker font size
|
264
|
+
#
|
265
|
+
def marker_font_size=(value)
|
266
|
+
@marker_font.size = value
|
267
|
+
end
|
268
|
+
|
269
|
+
# Optionally set the size of the font. Based on an 800x600px graph.
|
270
|
+
# Default is +20+.
|
271
|
+
#
|
272
|
+
# Will be scaled down if the graph is smaller than 800px wide.
|
273
|
+
#
|
274
|
+
# @param value [Numeric] legend font size
|
275
|
+
#
|
276
|
+
def legend_font_size=(value)
|
277
|
+
@legend_font.size = value
|
278
|
+
end
|
279
|
+
|
280
|
+
# Specifies whether to draw the title bolded or not. Default is +true+.
|
281
|
+
#
|
282
|
+
# @param value [Boolean] specifies whether to draw the title bolded or not.
|
283
|
+
#
|
284
|
+
def bold_title=(value)
|
285
|
+
@title_font.bold = value
|
286
|
+
end
|
287
|
+
|
288
|
+
# Specifies the text color.
|
289
|
+
#
|
290
|
+
# @param value [String] color
|
291
|
+
#
|
292
|
+
def font_color=(value)
|
293
|
+
@title_font.color = value
|
294
|
+
@marker_font.color = value
|
295
|
+
@legend_font.color = value
|
263
296
|
end
|
264
297
|
|
265
298
|
# Add a color to the list of available colors for lines.
|
@@ -328,12 +361,13 @@ module Gruff
|
|
328
361
|
}
|
329
362
|
@theme_options = defaults.merge options
|
330
363
|
|
364
|
+
self.marker_color = @theme_options[:marker_color]
|
365
|
+
self.font_color = @theme_options[:font_color] || @marker_color
|
366
|
+
|
331
367
|
@colors = @theme_options[:colors]
|
332
|
-
@marker_color = @theme_options[:marker_color]
|
333
368
|
@marker_shadow_color = @theme_options[:marker_shadow_color]
|
334
|
-
@font_color = @theme_options[:font_color] || @marker_color
|
335
369
|
|
336
|
-
Gruff::Renderer.
|
370
|
+
@renderer = Gruff::Renderer.new(@columns, @rows, @scale, @theme_options)
|
337
371
|
end
|
338
372
|
|
339
373
|
# Apply Apple's keynote theme.
|
@@ -435,8 +469,8 @@ module Gruff
|
|
435
469
|
def to_image
|
436
470
|
@to_image ||= begin
|
437
471
|
draw
|
438
|
-
|
439
|
-
|
472
|
+
renderer.finish
|
473
|
+
renderer.image
|
440
474
|
end
|
441
475
|
end
|
442
476
|
|
@@ -452,27 +486,29 @@ module Gruff
|
|
452
486
|
end
|
453
487
|
end
|
454
488
|
|
455
|
-
|
456
|
-
|
457
|
-
# Overridden by subclasses to do the actual plotting of the graph.
|
458
|
-
#
|
459
|
-
# Subclasses should start by calling super() for this method.
|
489
|
+
# Draw a graph.
|
460
490
|
def draw
|
491
|
+
setup_data
|
492
|
+
|
461
493
|
# Maybe should be done in one of the following functions for more granularity.
|
462
494
|
unless data_given?
|
463
495
|
draw_no_data
|
464
496
|
return
|
465
497
|
end
|
466
498
|
|
467
|
-
setup_data
|
468
499
|
setup_drawing
|
469
500
|
|
470
501
|
draw_legend
|
471
502
|
draw_line_markers
|
472
503
|
draw_axis_labels
|
473
504
|
draw_title
|
505
|
+
draw_graph
|
474
506
|
end
|
475
507
|
|
508
|
+
protected
|
509
|
+
|
510
|
+
attr_reader :renderer
|
511
|
+
|
476
512
|
# Perform data manipulation before calculating chart measurements
|
477
513
|
def setup_data # :nodoc:
|
478
514
|
if @y_axis_increment && !@hide_line_markers
|
@@ -577,13 +613,13 @@ module Gruff
|
|
577
613
|
x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN + @marker_caps_height
|
578
614
|
|
579
615
|
# TODO: Center between graph area
|
580
|
-
text_renderer = Gruff::Renderer::Text.new(@x_axis_label, font: @
|
616
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, @x_axis_label, font: @marker_font)
|
581
617
|
text_renderer.add_to_render_queue(@raw_columns, 1.0, 0.0, x_axis_label_y_coordinate)
|
582
618
|
end
|
583
619
|
|
584
620
|
if @y_axis_label
|
585
621
|
# Y Axis, rotated vertically
|
586
|
-
text_renderer = Gruff::Renderer::Text.new(@y_axis_label, font: @
|
622
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, @y_axis_label, font: @marker_font, rotation: -90)
|
587
623
|
text_renderer.add_to_render_queue(1.0, @raw_rows, @left_margin + @marker_caps_height / 2.0, 0.0, Magick::CenterGravity)
|
588
624
|
end
|
589
625
|
end
|
@@ -598,13 +634,13 @@ module Gruff
|
|
598
634
|
(0..marker_count).each do |index|
|
599
635
|
y = @graph_top + @graph_height - index.to_f * increment_scaled
|
600
636
|
|
601
|
-
line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
|
637
|
+
line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
|
602
638
|
line_renderer.render(@graph_left, y, @graph_right, y)
|
603
639
|
|
604
640
|
unless @hide_line_numbers
|
605
641
|
marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
|
606
|
-
label =
|
607
|
-
text_renderer = Gruff::Renderer::Text.new(label, font: @
|
642
|
+
label = y_axis_label(marker_label, @increment)
|
643
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
|
608
644
|
text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y, Magick::EastGravity)
|
609
645
|
end
|
610
646
|
end
|
@@ -627,7 +663,7 @@ module Gruff
|
|
627
663
|
current_x_offset = center(label_widths.first.sum)
|
628
664
|
current_y_offset = begin
|
629
665
|
if @legend_at_bottom
|
630
|
-
@
|
666
|
+
@graph_bottom + @legend_margin + @legend_caps_height + LABEL_MARGIN
|
631
667
|
else
|
632
668
|
hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + @title_caps_height
|
633
669
|
end
|
@@ -637,17 +673,17 @@ module Gruff
|
|
637
673
|
next if legend_label.empty?
|
638
674
|
|
639
675
|
# Draw label
|
640
|
-
text_renderer = Gruff::Renderer::Text.new(legend_label, font: @
|
676
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, legend_label, font: @legend_font)
|
641
677
|
text_renderer.add_to_render_queue(@raw_columns, 1.0, current_x_offset + (legend_square_width * 1.7), current_y_offset, Magick::WestGravity)
|
642
678
|
|
643
679
|
# Now draw box with color of this dataset
|
644
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(color: store.data[index].color)
|
680
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
|
645
681
|
rect_renderer.render(current_x_offset,
|
646
682
|
current_y_offset - legend_square_width / 2.0,
|
647
683
|
current_x_offset + legend_square_width,
|
648
684
|
current_y_offset + legend_square_width / 2.0)
|
649
685
|
|
650
|
-
width = calculate_width(@
|
686
|
+
width = calculate_width(@legend_font, legend_label)
|
651
687
|
current_x_offset += width + (legend_square_width * 2.7)
|
652
688
|
label_widths.first.shift
|
653
689
|
|
@@ -659,8 +695,6 @@ module Gruff
|
|
659
695
|
unless label_widths.empty?
|
660
696
|
# Wrap to next line and shrink available graph dimensions
|
661
697
|
current_y_offset += line_height
|
662
|
-
@graph_top += line_height
|
663
|
-
@graph_height = @graph_bottom - @graph_top
|
664
698
|
end
|
665
699
|
end
|
666
700
|
end
|
@@ -670,15 +704,12 @@ module Gruff
|
|
670
704
|
def draw_title
|
671
705
|
return if hide_title?
|
672
706
|
|
673
|
-
|
674
|
-
font_weight = @bold_title ? Magick::BoldWeight : Magick::NormalWeight
|
675
|
-
font_size = @title_font_size
|
676
|
-
|
677
|
-
metrics = Renderer::Text.metrics(@title, font_size, font_weight)
|
707
|
+
metrics = Gruff::Renderer::Text.new(renderer, @title, font: @title_font).metrics
|
678
708
|
if metrics.width > @raw_columns
|
679
|
-
|
709
|
+
@title_font.size = @title_font.size * (@raw_columns / metrics.width) * 0.95
|
680
710
|
end
|
681
|
-
|
711
|
+
|
712
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, @title, font: @title_font)
|
682
713
|
text_renderer.add_to_render_queue(@raw_columns, 1.0, 0, @top_margin)
|
683
714
|
end
|
684
715
|
|
@@ -691,14 +722,11 @@ module Gruff
|
|
691
722
|
|
692
723
|
# TESTME
|
693
724
|
# FIXME: Consider chart types other than bar
|
694
|
-
# TODO: See if index.odd? is the best
|
725
|
+
# TODO: See if index.odd? is the best strategy
|
695
726
|
y_offset += @label_stagger_height if index.odd?
|
696
727
|
|
697
|
-
label_text = truncate_label_text(@labels[index].to_s)
|
698
|
-
|
699
728
|
if x_offset >= @graph_left && x_offset <= @graph_right
|
700
|
-
|
701
|
-
text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset, gravity)
|
729
|
+
draw_label_at(1.0, 1.0, x_offset, y_offset, @labels[index], gravity)
|
702
730
|
end
|
703
731
|
end
|
704
732
|
end
|
@@ -713,20 +741,33 @@ module Gruff
|
|
713
741
|
end
|
714
742
|
end
|
715
743
|
|
744
|
+
def draw_label_at(width, height, x, y, text, gravity = Magick::NorthGravity)
|
745
|
+
label_text = truncate_label_text(text)
|
746
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, label_text, font: @marker_font)
|
747
|
+
text_renderer.add_to_render_queue(width, height, x, y, gravity)
|
748
|
+
end
|
749
|
+
|
716
750
|
# Draws the data value over the data point in bar graphs
|
717
|
-
def draw_value_label(x_offset, y_offset, data_point
|
718
|
-
return if @hide_line_markers
|
751
|
+
def draw_value_label(x_offset, y_offset, data_point)
|
752
|
+
return if @hide_line_markers
|
719
753
|
|
720
|
-
text_renderer = Gruff::Renderer::Text.new(data_point, font: @
|
754
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, data_point, font: @marker_font)
|
721
755
|
text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
|
722
756
|
end
|
723
757
|
|
724
758
|
# Shows an error message because you have no data.
|
725
759
|
def draw_no_data
|
726
|
-
|
760
|
+
font = @title_font.dup
|
761
|
+
font.size = 80
|
762
|
+
font.bold = false
|
763
|
+
text_renderer = Gruff::Renderer::Text.new(renderer, @no_data_message, font: font)
|
727
764
|
text_renderer.render(@raw_columns, @raw_rows, 0, 0, Magick::CenterGravity)
|
728
765
|
end
|
729
766
|
|
767
|
+
def draw_graph
|
768
|
+
raise 'Should implement this method at inherited class.'
|
769
|
+
end
|
770
|
+
|
730
771
|
# Resets everything to defaults (except data).
|
731
772
|
def reset_themes
|
732
773
|
@theme_options = {}
|
@@ -742,7 +783,7 @@ module Gruff
|
|
742
783
|
end
|
743
784
|
|
744
785
|
def clip_value_if_greater_than(value, max_value) # :nodoc:
|
745
|
-
|
786
|
+
value > max_value ? max_value : value
|
746
787
|
end
|
747
788
|
|
748
789
|
def significant(i) # :nodoc:
|
@@ -789,15 +830,15 @@ module Gruff
|
|
789
830
|
private
|
790
831
|
|
791
832
|
def setup_marker_caps_height
|
792
|
-
hide_bottom_label_area? ? 0 : calculate_caps_height(@
|
833
|
+
hide_bottom_label_area? ? 0 : calculate_caps_height(@marker_font)
|
793
834
|
end
|
794
835
|
|
795
836
|
def setup_title_caps_height
|
796
|
-
hide_title? ? 0 : calculate_caps_height(@
|
837
|
+
hide_title? ? 0 : calculate_caps_height(@title_font) * @title.lines.to_a.size
|
797
838
|
end
|
798
839
|
|
799
840
|
def setup_legend_caps_height
|
800
|
-
@hide_legend ? 0 : calculate_caps_height(@
|
841
|
+
@hide_legend ? 0 : calculate_caps_height(@legend_font)
|
801
842
|
end
|
802
843
|
|
803
844
|
def graph_right_margin
|
@@ -808,7 +849,7 @@ module Gruff
|
|
808
849
|
# Make space for half the width of the rightmost column label.
|
809
850
|
# Might be greater than the number of columns if between-style bar markers are used.
|
810
851
|
last_label = @labels.keys.max.to_i
|
811
|
-
|
852
|
+
last_label >= (column_count - 1) && @center_labels_over_point ? calculate_width(@marker_font, @labels[last_label]) / 2.0 : 0
|
812
853
|
end
|
813
854
|
|
814
855
|
def setup_left_margin
|
@@ -816,12 +857,12 @@ module Gruff
|
|
816
857
|
|
817
858
|
text = begin
|
818
859
|
if @has_left_labels
|
819
|
-
@labels.values.reduce('') { |value, memo|
|
860
|
+
@labels.values.reduce('') { |value, memo| value.to_s.length > memo.to_s.length ? value : memo }
|
820
861
|
else
|
821
|
-
|
862
|
+
y_axis_label(maximum_value.to_f, @increment)
|
822
863
|
end
|
823
864
|
end
|
824
|
-
longest_left_label_width = calculate_width(@
|
865
|
+
longest_left_label_width = calculate_width(@marker_font, truncate_label_text(text))
|
825
866
|
longest_left_label_width *= 1.25 if @has_left_labels
|
826
867
|
|
827
868
|
# Shift graph if left line numbers are hidden
|
@@ -831,17 +872,16 @@ module Gruff
|
|
831
872
|
end
|
832
873
|
|
833
874
|
def setup_top_margin
|
834
|
-
return @top_margin if @legend_at_bottom
|
835
|
-
|
836
875
|
# When @hide title, leave a title_margin space for aesthetics.
|
837
876
|
# Same with @hide_legend
|
838
877
|
@top_margin +
|
839
878
|
(hide_title? ? @title_margin : @title_caps_height + @title_margin) +
|
840
|
-
(@hide_legend ? @legend_margin :
|
879
|
+
(@hide_legend || @legend_at_bottom ? @legend_margin : calculate_legend_height + @legend_margin)
|
841
880
|
end
|
842
881
|
|
843
882
|
def setup_bottom_margin
|
844
883
|
graph_bottom_margin = hide_bottom_label_area? ? @bottom_margin : @bottom_margin + @marker_caps_height + LABEL_MARGIN
|
884
|
+
graph_bottom_margin += (calculate_legend_height + @legend_margin) if @legend_at_bottom
|
845
885
|
|
846
886
|
x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN
|
847
887
|
# FIXME: Consider chart types other than bar
|
@@ -849,6 +889,7 @@ module Gruff
|
|
849
889
|
end
|
850
890
|
|
851
891
|
def truncate_label_text(text)
|
892
|
+
text = text.to_s
|
852
893
|
return text if text.size <= @label_max_size
|
853
894
|
|
854
895
|
if @label_truncation_style == :trailing_dots
|
@@ -863,40 +904,58 @@ module Gruff
|
|
863
904
|
# Return a formatted string representing a number value that should be
|
864
905
|
# printed as a label.
|
865
906
|
def label(value, increment)
|
866
|
-
label =
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
907
|
+
label = begin
|
908
|
+
if increment
|
909
|
+
if increment >= 10 || (increment * 1) == (increment * 1).to_i.to_f
|
910
|
+
sprintf('%0i', value)
|
911
|
+
elsif increment >= 1.0 || (increment * 10) == (increment * 10).to_i.to_f
|
912
|
+
sprintf('%0.1f', value)
|
913
|
+
elsif increment >= 0.1 || (increment * 100) == (increment * 100).to_i.to_f
|
914
|
+
sprintf('%0.2f', value)
|
915
|
+
elsif increment >= 0.01 || (increment * 1000) == (increment * 1000).to_i.to_f
|
916
|
+
sprintf('%0.3f', value)
|
917
|
+
elsif increment >= 0.001 || (increment * 10_000) == (increment * 10_000).to_i.to_f
|
918
|
+
sprintf('%0.4f', value)
|
919
|
+
else
|
920
|
+
value.to_s
|
921
|
+
end
|
922
|
+
elsif (@spread.to_f % (marker_count.to_f == 0 ? 1 : marker_count.to_f) == 0) || !@y_axis_increment.nil?
|
923
|
+
value.to_i.to_s
|
924
|
+
elsif @spread > 10.0
|
925
|
+
sprintf('%0i', value)
|
926
|
+
elsif @spread >= 3.0
|
927
|
+
sprintf('%0.2f', value)
|
928
|
+
else
|
929
|
+
value.to_s
|
930
|
+
end
|
931
|
+
end
|
889
932
|
|
890
933
|
parts = label.split('.')
|
891
934
|
parts[0] = parts[0].commify
|
892
935
|
parts.join('.')
|
893
936
|
end
|
894
937
|
|
938
|
+
def x_axis_label(value, increment)
|
939
|
+
if @x_axis_label_format
|
940
|
+
@x_axis_label_format.call(value)
|
941
|
+
else
|
942
|
+
label(value, increment)
|
943
|
+
end
|
944
|
+
end
|
945
|
+
|
946
|
+
def y_axis_label(value, increment)
|
947
|
+
if @y_axis_label_format
|
948
|
+
@y_axis_label_format.call(value)
|
949
|
+
else
|
950
|
+
label(value, increment)
|
951
|
+
end
|
952
|
+
end
|
953
|
+
|
895
954
|
def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
|
896
955
|
# May fix legend drawing problem at small sizes
|
897
956
|
label_widths = [[]] # Used to calculate line wrap
|
898
957
|
legend_labels.each do |label|
|
899
|
-
width = calculate_width(@
|
958
|
+
width = calculate_width(@legend_font, label)
|
900
959
|
label_width = width + legend_square_width * 2.7
|
901
960
|
label_widths.last.push label_width
|
902
961
|
|
@@ -908,13 +967,38 @@ module Gruff
|
|
908
967
|
label_widths
|
909
968
|
end
|
910
969
|
|
970
|
+
def calculate_legend_height
|
971
|
+
return 0.0 if @hide_legend
|
972
|
+
|
973
|
+
legend_labels = store.data.map(&:label)
|
974
|
+
legend_square_width = @legend_box_size
|
975
|
+
label_widths = calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
|
976
|
+
legend_height = 0.0
|
977
|
+
|
978
|
+
legend_labels.each_with_index do |legend_label, _index|
|
979
|
+
next if legend_label.empty?
|
980
|
+
|
981
|
+
label_widths.first.shift
|
982
|
+
if label_widths.first.empty?
|
983
|
+
label_widths.shift
|
984
|
+
line_height = [@legend_caps_height, legend_square_width].max + @legend_margin
|
985
|
+
unless label_widths.empty?
|
986
|
+
# Wrap to next line and shrink available graph dimensions
|
987
|
+
legend_height += line_height
|
988
|
+
end
|
989
|
+
end
|
990
|
+
end
|
991
|
+
|
992
|
+
legend_height + @legend_caps_height
|
993
|
+
end
|
994
|
+
|
911
995
|
# Returns the height of the capital letter 'X' for the current font and
|
912
996
|
# size.
|
913
997
|
#
|
914
998
|
# Not scaled since it deals with dimensions that the regular scaling will
|
915
999
|
# handle.
|
916
|
-
def calculate_caps_height(
|
917
|
-
metrics = Renderer::Text.
|
1000
|
+
def calculate_caps_height(font)
|
1001
|
+
metrics = Gruff::Renderer::Text.new(renderer, 'X', font: font).metrics
|
918
1002
|
metrics.height
|
919
1003
|
end
|
920
1004
|
|
@@ -922,11 +1006,11 @@ module Gruff
|
|
922
1006
|
#
|
923
1007
|
# Not scaled since it deals with dimensions that the regular
|
924
1008
|
# scaling will handle.
|
925
|
-
def calculate_width(
|
1009
|
+
def calculate_width(font, text)
|
926
1010
|
text = text.to_s
|
927
1011
|
return 0 if text.empty?
|
928
1012
|
|
929
|
-
metrics = Renderer::Text.
|
1013
|
+
metrics = Gruff::Renderer::Text.new(renderer, text, font: font).metrics
|
930
1014
|
metrics.width
|
931
1015
|
end
|
932
1016
|
|
@@ -935,7 +1019,7 @@ module Gruff
|
|
935
1019
|
# Try to use a number of horizontal lines that will come out even.
|
936
1020
|
#
|
937
1021
|
# TODO Do the same for larger numbers...100, 75, 50, 25
|
938
|
-
@increment =
|
1022
|
+
@increment = @spread > 0 && marker_count > 0 ? significant(@spread / marker_count) : 1
|
939
1023
|
else
|
940
1024
|
# TODO: Make this work for negative values
|
941
1025
|
self.marker_count = (@spread / @y_axis_increment).to_i
|
data/lib/gruff/bezier.rb
CHANGED
@@ -19,11 +19,9 @@
|
|
19
19
|
# g.write('bezier.png')
|
20
20
|
#
|
21
21
|
class Gruff::Bezier < Gruff::Base
|
22
|
-
|
23
|
-
super
|
24
|
-
|
25
|
-
return unless data_given?
|
22
|
+
private
|
26
23
|
|
24
|
+
def draw_graph
|
27
25
|
x_increment = @graph_width / (column_count - 1).to_f
|
28
26
|
|
29
27
|
store.norm_data.each do |data_row|
|
@@ -48,9 +46,9 @@ class Gruff::Bezier < Gruff::Base
|
|
48
46
|
stroke_width = clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
49
47
|
|
50
48
|
if RUBY_PLATFORM == 'java'
|
51
|
-
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)
|
52
50
|
else
|
53
|
-
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)
|
54
52
|
end
|
55
53
|
end
|
56
54
|
end
|