gruff 0.3.1 → 0.3.3

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.
data.tar.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ K���L'G�X��W�R=r�a<p�"D�Íj/��P���G���CU&��ܱ��{s�ƈvE��
2
+ �_��P�{�76��oފ��I@u3BJ���$q��QXA
3
+ �7���u�&Wؔ5�uZ���m�F�c���s;�"�h�ԑx�%�qP�R�K(x?g�v�S1ҼV���ں|�
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.3.3
2
+
3
+ * Legend line wrapping [Mat Schaffer]
4
+ * Stacked area graph fixes [James Coglan]
5
+
6
+ == 0.3.2
7
+
8
+ * Include init.rb for use as a Rails plugin.
9
+
1
10
  == 0.3.1
2
11
 
3
12
  * Fixed missing bullet graph bug (experimental, will be in a future release).
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005 Geoffrey Grosenbach boss@topfunky.com
1
+ Copyright (c) 2005-2008 Topfunky Corporation boss@topfunky.com
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/Manifest.txt CHANGED
@@ -30,12 +30,14 @@ assets/pc306715.jpg
30
30
  assets/plastik/blue.png
31
31
  assets/plastik/green.png
32
32
  assets/plastik/red.png
33
+ init.rb
33
34
  lib/gruff.rb
34
35
  lib/gruff/accumulator_bar.rb
35
36
  lib/gruff/area.rb
36
37
  lib/gruff/bar.rb
37
38
  lib/gruff/bar_conversion.rb
38
39
  lib/gruff/base.rb
40
+ lib/gruff/bullet.rb
39
41
  lib/gruff/deprecated.rb
40
42
  lib/gruff/line.rb
41
43
  lib/gruff/mini/bar.rb
@@ -52,11 +54,15 @@ lib/gruff/spider.rb
52
54
  lib/gruff/stacked_area.rb
53
55
  lib/gruff/stacked_bar.rb
54
56
  lib/gruff/stacked_mixin.rb
57
+ rails_generators/gruff/gruff_generator.rb
58
+ rails_generators/gruff/templates/controller.rb
59
+ rails_generators/gruff/templates/functional_test.rb
55
60
  test/gruff_test_case.rb
56
61
  test/test_accumulator_bar.rb
57
62
  test/test_area.rb
58
63
  test/test_bar.rb
59
64
  test/test_base.rb
65
+ test/test_bullet.rb
60
66
  test/test_legend.rb
61
67
  test/test_line.rb
62
68
  test/test_mini_bar.rb
@@ -69,4 +75,5 @@ test/test_scene.rb
69
75
  test/test_side_bar.rb
70
76
  test/test_sidestacked_bar.rb
71
77
  test/test_spider.rb
78
+ test/test_stacked_area.rb
72
79
  test/test_stacked_bar.rb
data/README.txt CHANGED
@@ -2,13 +2,22 @@
2
2
 
3
3
  A library for making beautiful graphs.
4
4
 
5
- See samples at http://nubyonrails.com/pages/gruff
5
+ == Samples
6
6
 
7
- See the test suite in test/line_test.rb for examples.
7
+ http://nubyonrails.com/pages/gruff
8
8
 
9
9
  == Documentation
10
10
 
11
- Most of the documentation is in the Gruff::Base class.
11
+ http://gruff.rubyforge.org
12
+
13
+ See the test suite in test/line_test.rb for examples.
14
+
15
+ == Rails Plugin
16
+
17
+ Gruff is easy to use with Rails.
18
+
19
+ gem install gruff
20
+ cd vendor/plugins && gem unpack gruff
12
21
 
13
22
  == WARNING
14
23
 
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ Hoe.new('Gruff', Gruff::VERSION) do |p|
15
15
  p.remote_rdoc_dir = '' # Release to root
16
16
  end
17
17
 
18
- desc "Simple test on packaged files to make sure they are all there"
18
+ desc "Simple require on packaged files to make sure they are all there"
19
19
  task :verify => :package do
20
20
  # An error message will be displayed if files are missing
21
21
  if system %(ruby -e "require 'pkg/gruff-#{Gruff::VERSION}/lib/gruff'")
@@ -23,6 +23,8 @@ task :verify => :package do
23
23
  end
24
24
  end
25
25
 
26
+ task :release => :verify
27
+
26
28
  namespace :test do
27
29
 
28
30
  desc "Run mini tests"
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # For Rails
2
+ require 'gruff'
data/lib/gruff/area.rb CHANGED
@@ -16,7 +16,7 @@ class Gruff::Area < Gruff::Base
16
16
  prev_x = prev_y = 0.0
17
17
  @d = @d.fill data_row[DATA_COLOR_INDEX]
18
18
 
19
- data_row[1].each_with_index do |data_point, index|
19
+ data_row[DATA_VALUES_INDEX].each_with_index do |data_point, index|
20
20
  # Use incremented x and scaled y
21
21
  new_x = @graph_left + (@x_increment * index)
22
22
  new_y = @graph_top + (@graph_height - data_point * @graph_height)
data/lib/gruff/bar.rb CHANGED
@@ -51,7 +51,7 @@ protected
51
51
  # iterate over all normalised data
52
52
  @norm_data.each_with_index do |data_row, row_index|
53
53
 
54
- data_row[1].each_with_index do |data_point, point_index|
54
+ data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
55
55
  # Use incremented x and scaled y
56
56
  # x
57
57
  left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index)))
data/lib/gruff/base.rb CHANGED
@@ -3,6 +3,7 @@ require 'RMagick'
3
3
 
4
4
  require File.dirname(__FILE__) + '/deprecated'
5
5
 
6
+ ##
6
7
  # = Gruff. Graphs.
7
8
  #
8
9
  # Author:: Geoffrey Grosenbach boss@topfunky.com
@@ -15,10 +16,11 @@ require File.dirname(__FILE__) + '/deprecated'
15
16
  # Breijs, Richard Cowin, and a cast of thousands.
16
17
  #
17
18
  # See Gruff::Base#theme= for setting themes.
19
+
18
20
  module Gruff
19
21
 
20
22
  # This is the version of Gruff you are using.
21
- VERSION = '0.3.1'
23
+ VERSION = '0.3.3'
22
24
 
23
25
  class Base
24
26
 
@@ -26,7 +28,7 @@ module Gruff
26
28
  include Deprecated
27
29
 
28
30
  # Draw extra lines showing where the margins and text centers are
29
- DEBUG = false
31
+ DEBUG = true
30
32
 
31
33
  # Used for navigating the array of data to plot
32
34
  DATA_LABEL_INDEX = 0
@@ -176,7 +178,7 @@ module Gruff
176
178
  @rows = geometric_height.to_f
177
179
  else
178
180
  @columns = target_width.to_f
179
- @rows = target_width.to_f * 0.75
181
+ @rows = target_width.to_f * 0.75
180
182
  end
181
183
 
182
184
  initialize_ivars
@@ -213,7 +215,7 @@ module Gruff
213
215
  @marker_font_size = 21.0
214
216
  @legend_font_size = 20.0
215
217
  @title_font_size = 36.0
216
-
218
+
217
219
  @legend_box_size = 20.0
218
220
 
219
221
  @no_data_message = "No Data"
@@ -222,10 +224,10 @@ module Gruff
222
224
  @center_labels_over_point = true
223
225
  @has_left_labels = false
224
226
 
225
- @additional_line_values = []
227
+ @additional_line_values = []
226
228
  @additional_line_colors = []
227
229
  @theme_options = {}
228
-
230
+
229
231
  @x_axis_label = @y_axis_label = nil
230
232
  @y_axis_increment = nil
231
233
  @stacked = nil
@@ -276,7 +278,7 @@ module Gruff
276
278
  #
277
279
  def theme=(options)
278
280
  reset_themes()
279
-
281
+
280
282
  defaults = {
281
283
  :colors => ['black', 'white'],
282
284
  :additional_line_colors => [],
@@ -291,7 +293,7 @@ module Gruff
291
293
  @marker_color = @theme_options[:marker_color]
292
294
  @font_color = @theme_options[:font_color] || @marker_color
293
295
  @additional_line_colors = @theme_options[:additional_line_colors]
294
-
296
+
295
297
  render_background
296
298
  end
297
299
 
@@ -347,7 +349,7 @@ module Gruff
347
349
  @light_grey = '#999999'
348
350
  @black = 'black'
349
351
  @colors = [@green, @grey, @orange, @red, @white, @light_grey, @black]
350
-
352
+
351
353
  self.theme = {
352
354
  :colors => @colors,
353
355
  :marker_color => 'white',
@@ -367,7 +369,7 @@ module Gruff
367
369
  @dark_blue = '#3a5b87'
368
370
  @black = 'black'
369
371
  @colors = [@grey, @white, @dark_blue, @dark_pink, @green, @light_grey, @black]
370
-
372
+
371
373
  self.theme = {
372
374
  :colors => @colors,
373
375
  :marker_color => 'white',
@@ -380,15 +382,15 @@ module Gruff
380
382
  def theme_pastel
381
383
  # Colors
382
384
  @colors = [
383
- '#a9dada', # blue
384
- '#aedaa9', # green
385
- '#daaea9', # peach
386
- '#dadaa9', # yellow
387
- '#a9a9da', # dk purple
388
- '#daaeda', # purple
389
- '#dadada' # grey
390
- ]
391
-
385
+ '#a9dada', # blue
386
+ '#aedaa9', # green
387
+ '#daaea9', # peach
388
+ '#dadaa9', # yellow
389
+ '#a9a9da', # dk purple
390
+ '#daaeda', # purple
391
+ '#dadada' # grey
392
+ ]
393
+
392
394
  self.theme = {
393
395
  :colors => @colors,
394
396
  :marker_color => '#aea9a9', # Grey
@@ -401,14 +403,14 @@ module Gruff
401
403
  def theme_greyscale
402
404
  # Colors
403
405
  @colors = [
404
- '#282828', #
405
- '#383838', #
406
- '#686868', #
407
- '#989898', #
408
- '#c8c8c8', #
409
- '#e8e8e8', #
410
- ]
411
-
406
+ '#282828', #
407
+ '#383838', #
408
+ '#686868', #
409
+ '#989898', #
410
+ '#c8c8c8', #
411
+ '#e8e8e8', #
412
+ ]
413
+
412
414
  self.theme = {
413
415
  :colors => @colors,
414
416
  :marker_color => '#aea9a9', # Grey
@@ -440,7 +442,7 @@ module Gruff
440
442
  # Pre-normalize
441
443
  data_points.each_with_index do |data_point, index|
442
444
  next if data_point.nil?
443
-
445
+
444
446
  # Setup max/min so spread starts at the low end of the data points
445
447
  if @maximum_value.nil? && @minimum_value.nil?
446
448
  @maximum_value = @minimum_value = data_point
@@ -450,9 +452,9 @@ module Gruff
450
452
  # Original: @maximum_value = larger_than_max?(data_point, index) ? max(data_point, index) : @maximum_value
451
453
  @maximum_value = larger_than_max?(data_point) ? data_point : @maximum_value
452
454
  @has_data = true if @maximum_value > 0
453
-
455
+
454
456
  @minimum_value = less_than_min?(data_point) ? data_point : @minimum_value
455
- @has_data = true if @minimum_value < 0
457
+ @has_data = true if @minimum_value < 0
456
458
  end
457
459
  end
458
460
 
@@ -469,13 +471,13 @@ module Gruff
469
471
  def to_blob(fileformat='PNG')
470
472
  draw()
471
473
  return @base_image.to_blob do
472
- self.format = fileformat
474
+ self.format = fileformat
473
475
  end
474
476
  end
475
477
 
476
-
477
478
 
478
- protected
479
+
480
+ protected
479
481
 
480
482
  # Overridden by subclasses to do the actual plotting of the graph.
481
483
  #
@@ -483,11 +485,11 @@ protected
483
485
  def draw
484
486
  make_stacked if @stacked
485
487
  setup_drawing
486
-
488
+
487
489
  debug {
488
490
  # Outer margin
489
- @d.rectangle( @left_margin, @top_margin,
490
- @raw_columns - @right_margin, @raw_rows - @bottom_margin)
491
+ @d.rectangle( @left_margin, @top_margin,
492
+ @raw_columns - @right_margin, @raw_rows - @bottom_margin)
491
493
  # Graph area box
492
494
  @d.rectangle( @graph_left, @graph_top, @graph_right, @graph_bottom)
493
495
  }
@@ -504,11 +506,11 @@ protected
504
506
  draw_no_data()
505
507
  return
506
508
  end
507
-
509
+
508
510
  normalize()
509
511
  setup_graph_measurements()
510
512
  sort_norm_data() if @sort # Sort norm_data with avg largest values set first (for display)
511
-
513
+
512
514
  draw_legend()
513
515
  draw_line_markers()
514
516
  draw_axis_labels()
@@ -520,9 +522,9 @@ protected
520
522
  if @norm_data.nil? || force
521
523
  @norm_data = []
522
524
  return unless @has_data
523
-
525
+
524
526
  calculate_spread
525
-
527
+
526
528
  @data.each do |data_row|
527
529
  norm_data_points = []
528
530
  data_row[DATA_VALUES_INDEX].each do |data_point|
@@ -542,47 +544,50 @@ protected
542
544
  @spread = @spread > 0 ? @spread : 1
543
545
  end
544
546
 
547
+ ##
545
548
  # Calculates size of drawable area, general font dimensions, etc.
549
+
546
550
  def setup_graph_measurements
547
551
  @marker_caps_height = @hide_line_markers ? 0 :
548
- calculate_caps_height(@marker_font_size)
552
+ calculate_caps_height(@marker_font_size)
549
553
  @title_caps_height = @hide_title ? 0 :
550
- calculate_caps_height(@title_font_size)
554
+ calculate_caps_height(@title_font_size)
551
555
  @legend_caps_height = @hide_legend ? 0 :
552
- calculate_caps_height(@legend_font_size)
556
+ calculate_caps_height(@legend_font_size)
553
557
 
554
558
  if @hide_line_markers
555
559
  (@graph_left,
556
- @graph_right_margin,
557
- @graph_bottom_margin) = [@left_margin, @right_margin, @bottom_margin]
560
+ @graph_right_margin,
561
+ @graph_bottom_margin) = [@left_margin, @right_margin, @bottom_margin]
558
562
  else
559
563
  longest_left_label_width = 0
560
564
  if @has_left_labels
561
565
  longest_left_label_width = calculate_width(@marker_font_size,
562
- labels.values.inject('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
566
+ labels.values.inject('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
563
567
  else
564
- longest_left_label_width = calculate_width(@marker_font_size,
565
- label(@maximum_value.to_f))
568
+ longest_left_label_width = calculate_width(@marker_font_size,
569
+ label(@maximum_value.to_f))
566
570
  end
567
571
 
568
572
  # Shift graph if left line numbers are hidden
569
- line_number_width = @hide_line_numbers && !@has_left_labels ?
570
- 0.0 :
571
- (longest_left_label_width + LABEL_MARGIN * 2)
573
+ line_number_width = @hide_line_numbers && !@has_left_labels ?
574
+ 0.0 :
575
+ (longest_left_label_width + LABEL_MARGIN * 2)
576
+
577
+ @graph_left = @left_margin +
578
+ line_number_width +
579
+ (@y_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN * 2)
572
580
 
573
- @graph_left = @left_margin +
574
- line_number_width +
575
- (@y_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN * 2)
576
581
  # Make space for half the width of the rightmost column label.
577
582
  # Might be greater than the number of columns if between-style bar markers are used.
578
583
  last_label = @labels.keys.sort.last.to_i
579
584
  extra_room_for_long_label = (last_label >= (@column_count-1) && @center_labels_over_point) ?
580
- calculate_width(@marker_font_size, @labels[last_label])/2.0 :
581
- 0
582
- @graph_right_margin = @right_margin + extra_room_for_long_label
583
-
584
- @graph_bottom_margin = @bottom_margin +
585
- @marker_caps_height + LABEL_MARGIN
585
+ calculate_width(@marker_font_size, @labels[last_label]) / 2.0 :
586
+ 0
587
+ @graph_right_margin = @right_margin + extra_room_for_long_label
588
+
589
+ @graph_bottom_margin = @bottom_margin +
590
+ @marker_caps_height + LABEL_MARGIN
586
591
  end
587
592
 
588
593
  @graph_right = @raw_columns - @graph_right_margin
@@ -590,12 +595,12 @@ protected
590
595
 
591
596
  # When @hide title, leave a TITLE_MARGIN space for aesthetics.
592
597
  # Same with @hide_legend
593
- @graph_top = @top_margin +
594
- (@hide_title ? TITLE_MARGIN : @title_caps_height + TITLE_MARGIN * 2) +
595
- (@hide_legend ? LEGEND_MARGIN : @legend_caps_height + LEGEND_MARGIN * 2)
598
+ @graph_top = @top_margin +
599
+ (@hide_title ? TITLE_MARGIN : @title_caps_height + TITLE_MARGIN * 2) +
600
+ (@hide_legend ? LEGEND_MARGIN : @legend_caps_height + LEGEND_MARGIN * 2)
596
601
 
597
602
  x_axis_label_height = @x_axis_label.nil? ? 0.0 :
598
- @marker_caps_height + LABEL_MARGIN
603
+ @marker_caps_height + LABEL_MARGIN
599
604
  @graph_bottom = @raw_rows - @graph_bottom_margin - x_axis_label_height
600
605
  @graph_height = @graph_bottom - @graph_top
601
606
  end
@@ -614,10 +619,10 @@ protected
614
619
  @d.stroke('transparent')
615
620
  @d.pointsize = scale_fontsize(@marker_font_size)
616
621
  @d.gravity = NorthGravity
617
- @d = @d.annotate_scaled( @base_image,
618
- @raw_columns, 1.0,
619
- 0.0, x_axis_label_y_coordinate,
620
- @x_axis_label, @scale)
622
+ @d = @d.annotate_scaled( @base_image,
623
+ @raw_columns, 1.0,
624
+ 0.0, x_axis_label_y_coordinate,
625
+ @x_axis_label, @scale)
621
626
  debug { @d.line 0.0, x_axis_label_y_coordinate, @raw_columns, x_axis_label_y_coordinate }
622
627
  end
623
628
 
@@ -625,10 +630,10 @@ protected
625
630
  # Y Axis, rotated vertically
626
631
  @d.rotation = 90.0
627
632
  @d.gravity = CenterGravity
628
- @d = @d.annotate_scaled( @base_image,
629
- 1.0, @raw_rows,
630
- @left_margin + @marker_caps_height / 2.0, 0.0,
631
- @y_axis_label, @scale)
633
+ @d = @d.annotate_scaled( @base_image,
634
+ 1.0, @raw_rows,
635
+ @left_margin + @marker_caps_height / 2.0, 0.0,
636
+ @y_axis_label, @scale)
632
637
  @d.rotation = -90.0
633
638
  end
634
639
  end
@@ -636,9 +641,9 @@ protected
636
641
  # Draws horizontal background lines and labels
637
642
  def draw_line_markers
638
643
  return if @hide_line_markers
639
-
644
+
640
645
  @d = @d.stroke_antialias false
641
-
646
+
642
647
  if @y_axis_increment.nil?
643
648
  # Try to use a number of horizontal lines that will come out even.
644
649
  #
@@ -659,7 +664,7 @@ protected
659
664
  @minimum_value = @minimum_value.floor
660
665
  calculate_spread
661
666
  normalize(true)
662
-
667
+
663
668
  @marker_count = (@spread / @y_axis_increment).to_i
664
669
  @increment = @y_axis_increment
665
670
  end
@@ -668,7 +673,7 @@ protected
668
673
  # Draw horizontal line markers and annotate with numbers
669
674
  (0..@marker_count).each do |index|
670
675
  y = @graph_top + @graph_height - index.to_f * @increment_scaled
671
-
676
+
672
677
  @d = @d.stroke(@marker_color)
673
678
  @d = @d.stroke_width 1
674
679
  @d = @d.line(@graph_left, y, @graph_right, y)
@@ -681,43 +686,61 @@ protected
681
686
  @d.stroke('transparent')
682
687
  @d.pointsize = scale_fontsize(@marker_font_size)
683
688
  @d.gravity = EastGravity
684
-
689
+
685
690
  # Vertically center with 1.0 for the height
686
- @d = @d.annotate_scaled( @base_image,
687
- @graph_left - LABEL_MARGIN, 1.0,
688
- 0.0, y,
689
- label(marker_label), @scale)
691
+ @d = @d.annotate_scaled( @base_image,
692
+ @graph_left - LABEL_MARGIN, 1.0,
693
+ 0.0, y,
694
+ label(marker_label), @scale)
690
695
  end
691
696
  end
692
-
697
+
693
698
  # # Submitted by a contibutor...the utility escapes me
694
699
  # i = 0
695
700
  # @additional_line_values.each do |value|
696
701
  # @increment_scaled = @graph_height.to_f / (@maximum_value.to_f / value)
697
- #
702
+ #
698
703
  # y = @graph_top + @graph_height - @increment_scaled
699
- #
704
+ #
700
705
  # @d = @d.stroke(@additional_line_colors[i])
701
706
  # @d = @d.line(@graph_left, y, @graph_right, y)
702
- #
703
- #
707
+ #
708
+ #
704
709
  # @d.fill = @additional_line_colors[i]
705
710
  # @d.font = @font if @font
706
711
  # @d.stroke('transparent')
707
712
  # @d.pointsize = scale_fontsize(@marker_font_size)
708
713
  # @d.gravity = EastGravity
709
- # @d = @d.annotate_scaled( @base_image,
714
+ # @d = @d.annotate_scaled( @base_image,
710
715
  # 100, 20,
711
- # -10, y - (@marker_font_size/2.0),
716
+ # -10, y - (@marker_font_size/2.0),
712
717
  # "", @scale)
713
- # i += 1
718
+ # i += 1
714
719
  # end
715
-
720
+
716
721
  @d = @d.stroke_antialias true
717
722
  end
718
723
 
719
- # Draws a legend with the names of the datasets matched to the colors used
720
- # to draw them.
724
+ ##
725
+ # Return the sum of values in an array.
726
+ #
727
+ # Duplicated to not conflict with active_support in Rails.
728
+
729
+ def sum(arr)
730
+ arr.inject(0) { |i, m| m + i }
731
+ end
732
+
733
+ ##
734
+ # Return a calculation of center
735
+
736
+ def center(size)
737
+ (@raw_columns - size) / 2
738
+ end
739
+
740
+ ##
741
+ # Draws a legend with the names of the datasets matched
742
+ # to the colors used to draw them.
743
+
721
744
  def draw_legend
722
745
  return if @hide_legend
723
746
 
@@ -729,23 +752,23 @@ protected
729
752
  @d.font = @font if @font
730
753
  @d.pointsize = @legend_font_size
731
754
 
732
- metrics = @d.get_type_metrics(@base_image, @legend_labels.join(''))
733
- legend_text_width = metrics.width
734
- legend_width = legend_text_width +
735
- (@legend_labels.length * legend_square_width * 2.7)
736
- legend_left = (@raw_columns - legend_width) / 2
737
- legend_increment = legend_width / @legend_labels.length.to_f
755
+ label_widths = [[]] # Used to calculate line wrap
756
+ @legend_labels.each do |label|
757
+ metrics = @d.get_type_metrics(@base_image, label.to_s)
758
+ label_width = metrics.width + legend_square_width * 2.7
759
+ label_widths.last.push label_width
760
+
761
+ if sum(label_widths.last) > (@raw_columns * 0.9)
762
+ label_widths.push [label_widths.last.pop]
763
+ end
764
+ end
738
765
 
739
- current_x_offset = legend_left
740
- current_y_offset = @hide_title ?
741
- @top_margin + LEGEND_MARGIN :
742
- @top_margin +
743
- TITLE_MARGIN + @title_caps_height +
744
- LEGEND_MARGIN
766
+ current_x_offset = center(sum(label_widths.first))
767
+ current_y_offset = @hide_title ?
768
+ @top_margin + LEGEND_MARGIN :
769
+ @top_margin + TITLE_MARGIN + @title_caps_height + LEGEND_MARGIN
745
770
 
746
- debug { @d.line 0.0, current_y_offset, @raw_columns, current_y_offset }
747
-
748
- @legend_labels.each_with_index do |legend_label, index|
771
+ @legend_labels.each_with_index do |legend_label, index|
749
772
 
750
773
  # Draw label
751
774
  @d.fill = @font_color
@@ -754,23 +777,40 @@ protected
754
777
  @d.stroke('transparent')
755
778
  @d.font_weight = NormalWeight
756
779
  @d.gravity = WestGravity
757
- @d = @d.annotate_scaled( @base_image,
758
- @raw_columns, 1.0,
759
- current_x_offset + (legend_square_width * 1.7), current_y_offset,
760
- legend_label.to_s, @scale)
761
-
780
+ @d = @d.annotate_scaled( @base_image,
781
+ @raw_columns, 1.0,
782
+ current_x_offset + (legend_square_width * 1.7), current_y_offset,
783
+ legend_label.to_s, @scale)
784
+
762
785
  # Now draw box with color of this dataset
763
786
  @d = @d.stroke('transparent')
764
787
  @d = @d.fill @data[index][DATA_COLOR_INDEX]
765
- @d = @d.rectangle(current_x_offset,
766
- current_y_offset - legend_square_width / 2.0,
767
- current_x_offset + legend_square_width,
768
- current_y_offset + legend_square_width / 2.0)
788
+ @d = @d.rectangle(current_x_offset,
789
+ current_y_offset - legend_square_width / 2.0,
790
+ current_x_offset + legend_square_width,
791
+ current_y_offset + legend_square_width / 2.0)
769
792
 
770
793
  @d.pointsize = @legend_font_size
771
794
  metrics = @d.get_type_metrics(@base_image, legend_label.to_s)
772
795
  current_string_offset = metrics.width + (legend_square_width * 2.7)
773
- current_x_offset += current_string_offset
796
+
797
+ # Handle wrapping
798
+ label_widths.first.shift
799
+ if label_widths.first.empty?
800
+ debug { @d.line 0.0, current_y_offset, @raw_columns, current_y_offset }
801
+
802
+ label_widths.shift
803
+ current_x_offset = center(sum(label_widths.first)) unless label_widths.empty?
804
+ line_height = [@legend_caps_height, legend_square_width].max + LEGEND_MARGIN
805
+ if label_widths.length > 0
806
+ # Wrap to next line and shrink available graph dimensions
807
+ current_y_offset += line_height
808
+ @graph_top += line_height
809
+ @graph_height = @graph_bottom - @graph_top
810
+ end
811
+ else
812
+ current_x_offset += current_string_offset
813
+ end
774
814
  end
775
815
  @color_index = 0
776
816
  end
@@ -785,10 +825,10 @@ protected
785
825
  @d.pointsize = scale_fontsize(@title_font_size)
786
826
  @d.font_weight = BoldWeight
787
827
  @d.gravity = NorthGravity
788
- @d = @d.annotate_scaled( @base_image,
789
- @raw_columns, 1.0,
790
- 0, @top_margin,
791
- @title, @scale)
828
+ @d = @d.annotate_scaled( @base_image,
829
+ @raw_columns, 1.0,
830
+ 0, @top_margin,
831
+ @title, @scale)
792
832
  end
793
833
 
794
834
  # Draws column labels below graph, centered over x_offset
@@ -807,9 +847,9 @@ protected
807
847
  @d.pointsize = scale_fontsize(@marker_font_size)
808
848
  @d.gravity = NorthGravity
809
849
  @d = @d.annotate_scaled(@base_image,
810
- 1.0, 1.0,
811
- x_offset, y_offset,
812
- @labels[index], @scale)
850
+ 1.0, 1.0,
851
+ x_offset, y_offset,
852
+ @labels[index], @scale)
813
853
  @labels_seen[index] = 1
814
854
  debug { @d.line 0.0, y_offset, @raw_columns, y_offset }
815
855
  end
@@ -817,16 +857,16 @@ protected
817
857
 
818
858
  # Shows an error message because you have no data.
819
859
  def draw_no_data
820
- @d.fill = @font_color
821
- @d.font = @font if @font
822
- @d.stroke('transparent')
823
- @d.font_weight = NormalWeight
824
- @d.pointsize = scale_fontsize(80)
825
- @d.gravity = CenterGravity
826
- @d = @d.annotate_scaled( @base_image,
827
- @raw_columns, @raw_rows/2.0,
828
- 0, 10,
829
- @no_data_message, @scale)
860
+ @d.fill = @font_color
861
+ @d.font = @font if @font
862
+ @d.stroke('transparent')
863
+ @d.font_weight = NormalWeight
864
+ @d.pointsize = scale_fontsize(80)
865
+ @d.gravity = CenterGravity
866
+ @d = @d.annotate_scaled( @base_image,
867
+ @raw_columns, @raw_rows/2.0,
868
+ 0, 10,
869
+ @no_data_message, @scale)
830
870
  end
831
871
 
832
872
  # Finds the best background to render based on the provided theme options.
@@ -852,8 +892,8 @@ protected
852
892
 
853
893
  # Use with a theme definition method to draw a gradiated background.
854
894
  def render_gradiated_background(top_color, bottom_color)
855
- Image.new(@columns, @rows,
856
- GradientFill.new(0, 0, 100, 0, top_color, bottom_color))
895
+ Image.new(@columns, @rows,
896
+ GradientFill.new(0, 0, 100, 0, top_color, bottom_color))
857
897
  end
858
898
 
859
899
  # Use with a theme to use an image (800x600 original) background.
@@ -903,7 +943,7 @@ protected
903
943
  data_point > @maximum_value
904
944
  end
905
945
 
906
- def less_than_min?(data_point, index=0) # :nodoc:
946
+ def less_than_min?(data_point, index=0) # :nodoc:
907
947
  data_point < @minimum_value
908
948
  end
909
949
 
@@ -913,7 +953,7 @@ protected
913
953
  end
914
954
 
915
955
  # Overridden by subclasses that need it.
916
- def min(data_point, index) # :nodoc:
956
+ def min(data_point, index) # :nodoc:
917
957
  data_point
918
958
  end
919
959
 
@@ -941,7 +981,7 @@ protected
941
981
  # Sort with largest overall summed value at front of array so it shows up
942
982
  # correctly in the drawn graph.
943
983
  def sort_norm_data
944
- @norm_data.sort! { |a,b| sums(b[1]) <=> sums(a[1]) }
984
+ @norm_data.sort! { |a,b| sums(b[DATA_VALUES_INDEX]) <=> sums(a[DATA_VALUES_INDEX]) }
945
985
  end
946
986
 
947
987
  def sums(data_set) # :nodoc:
@@ -973,14 +1013,14 @@ protected
973
1013
  def make_stacked # :nodoc:
974
1014
  stacked_values = Array.new(@column_count, 0)
975
1015
  @data.each do |value_set|
976
- value_set[1].each_with_index do |value, index|
1016
+ value_set[DATA_VALUES_INDEX].each_with_index do |value, index|
977
1017
  stacked_values[index] += value
978
1018
  end
979
- value_set[1] = stacked_values.dup
1019
+ value_set[DATA_VALUES_INDEX] = stacked_values.dup
980
1020
  end
981
1021
  end
982
1022
 
983
- private
1023
+ private
984
1024
 
985
1025
  # Takes a block and draws it if DEBUG is true.
986
1026
  #
@@ -1039,7 +1079,7 @@ private
1039
1079
 
1040
1080
  # Returns the width of a string at this pointsize.
1041
1081
  #
1042
- # Not scaled since it deals with dimensions that the regular
1082
+ # Not scaled since it deals with dimensions that the regular
1043
1083
  # scaling will handle.
1044
1084
  def calculate_width(font_size, text)
1045
1085
  @d.pointsize = font_size
@@ -1062,12 +1102,11 @@ module Magick
1062
1102
  scaled_height = (height * scale) >= 1 ? (height * scale) : 1
1063
1103
 
1064
1104
  self.annotate( img,
1065
- scaled_width, scaled_height,
1066
- x * scale, y * scale,
1067
- text)
1105
+ scaled_width, scaled_height,
1106
+ x * scale, y * scale,
1107
+ text)
1068
1108
  end
1069
1109
 
1070
1110
  end
1071
1111
 
1072
1112
  end # Magick
1073
-