gruff 0.12.2 → 0.15.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.
- 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
|