scruffy 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/CHANGES +8 -0
  2. data/History.txt +104 -0
  3. data/License.txt +20 -0
  4. data/Manifest.txt +105 -0
  5. data/PostInstall.txt +6 -0
  6. data/README.txt +66 -0
  7. data/Rakefile +108 -104
  8. data/config/hoe.rb +78 -0
  9. data/config/requirements.rb +15 -0
  10. data/lib/scruffy.rb +8 -6
  11. data/lib/scruffy/components/base.rb +4 -0
  12. data/lib/scruffy/components/legend.rb +65 -30
  13. data/lib/scruffy/components/viewport.rb +14 -17
  14. data/lib/scruffy/formatters.rb +1 -1
  15. data/lib/scruffy/graph.rb +18 -7
  16. data/lib/scruffy/graph_state.rb +24 -0
  17. data/lib/scruffy/helpers.rb +2 -1
  18. data/lib/scruffy/helpers/canvas.rb +19 -17
  19. data/lib/scruffy/helpers/layer_container.rb +8 -3
  20. data/lib/scruffy/helpers/meta.rb +5 -5
  21. data/lib/scruffy/helpers/point_container.rb +70 -0
  22. data/lib/scruffy/layers.rb +2 -0
  23. data/lib/scruffy/layers/average.rb +6 -1
  24. data/lib/scruffy/layers/bar.rb +1 -0
  25. data/lib/scruffy/layers/base.rb +38 -14
  26. data/lib/scruffy/layers/pie.rb +123 -0
  27. data/lib/scruffy/layers/pie_slice.rb +114 -0
  28. data/lib/scruffy/layers/scatter.rb +21 -0
  29. data/lib/scruffy/layers/sparkline_bar.rb +1 -0
  30. data/lib/scruffy/layers/stacked.rb +2 -5
  31. data/lib/scruffy/rasterizers/rmagick_rasterizer.rb +1 -2
  32. data/lib/scruffy/renderers.rb +2 -1
  33. data/lib/scruffy/renderers/base.rb +6 -4
  34. data/lib/scruffy/renderers/pie.rb +20 -0
  35. data/lib/scruffy/themes.rb +54 -4
  36. data/lib/scruffy/version.rb +8 -2
  37. data/script/console +10 -0
  38. data/script/destroy +14 -0
  39. data/script/generate +14 -0
  40. data/script/txt2html +82 -0
  41. data/setup.rb +1585 -0
  42. data/spec/scruffy/graph_spec.rb +175 -0
  43. data/spec/scruffy/layers/base_spec.rb +30 -0
  44. data/spec/{layers → scruffy/layers}/line_spec.rb +2 -1
  45. data/spec/spec_helper.rb +8 -0
  46. data/tasks/deployment.rake +34 -0
  47. data/tasks/environment.rake +7 -0
  48. data/tasks/website.rake +17 -0
  49. data/test/graph_creation_test.rb +101 -0
  50. data/test/test_helper.rb +2 -0
  51. data/test/test_scruffy.rb +11 -0
  52. data/website/images/blank.gif.html +7 -0
  53. data/website/images/graphs/all_smiles.png +0 -0
  54. data/website/images/graphs/bar_test.png +0 -0
  55. data/website/images/graphs/bar_test.svg +71 -0
  56. data/website/images/graphs/line_test.png +0 -0
  57. data/website/images/graphs/line_test.svg +60 -0
  58. data/website/images/graphs/multi_test.png +0 -0
  59. data/website/images/graphs/multi_test.svg +296 -0
  60. data/website/images/graphs/pie_test.png +0 -0
  61. data/website/images/graphs/pie_test.svg +40 -0
  62. data/website/images/graphs/split_test.png +0 -0
  63. data/website/images/graphs/split_test.svg +295 -0
  64. data/website/images/graphs/stacking_test.png +0 -0
  65. data/website/images/graphs/stacking_test.svg +146 -0
  66. data/website/images/header.png +0 -0
  67. data/website/images/header_gradient.png +0 -0
  68. data/website/images/overlay.png +0 -0
  69. data/website/images/scruffy.png +0 -0
  70. data/website/index.html +294 -0
  71. data/website/index.txt +199 -0
  72. data/website/javascripts/application.js +2 -0
  73. data/website/javascripts/controls.js +815 -0
  74. data/website/javascripts/dragdrop.js +913 -0
  75. data/website/javascripts/effects.js +958 -0
  76. data/website/javascripts/lightbox.js +437 -0
  77. data/website/javascripts/prototype.js +2006 -0
  78. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  79. data/website/stylesheets/lightbox.css +27 -0
  80. data/website/stylesheets/screen.css +147 -0
  81. data/website/stylesheets/scruffy.css +227 -0
  82. data/website/template.html.erb +47 -0
  83. metadata +135 -55
  84. data/spec/graph_spec.rb +0 -162
@@ -0,0 +1,175 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+ require 'scruffy'
3
+ require 'fileutils'
4
+
5
+ module CustomRenderers
6
+ def blank_renderer
7
+ object = Object.new
8
+ object.instance_eval { class << self;self;end }.instance_eval { define_method :render do |options|
9
+ puts "Rendering"
10
+ end
11
+ }
12
+ object
13
+ end
14
+ end
15
+
16
+ describe "A new Scruffy::Graph" do
17
+ include CustomRenderers
18
+
19
+ setup do
20
+ @graph = Scruffy::Graph.new
21
+ end
22
+
23
+ it "should have a blank title" do
24
+ @graph.title.should be_nil
25
+ end
26
+
27
+ it "should be set to the keynote theme" do
28
+ @graph.theme.class.should equal(Scruffy::Themes::Keynote)
29
+ end
30
+
31
+ it "should have zero layers" do
32
+ @graph.layers.should be_empty
33
+ end
34
+
35
+ it "should not have a default layer type" do
36
+ @graph.default_type.should be_nil
37
+ end
38
+
39
+ it "should not have any point markers (x-axis values)" do
40
+ @graph.point_markers.should be_nil
41
+ end
42
+
43
+ it "should format values as numbers by default" do
44
+ @graph.value_formatter.should be_instance_of(Scruffy::Formatters::Number)
45
+ end
46
+
47
+ it "should use a StandardRenderer" do
48
+ @graph.renderer.should_be be_instance_of(Scruffy::Renderers::Standard)
49
+ end
50
+
51
+ it "should accept a new title" do
52
+ @graph.title = "New Title"
53
+ @graph.title.should == "New Title"
54
+ end
55
+
56
+ it "should accept a new theme" do
57
+ @graph.theme = Scruffy::Themes::Mephisto
58
+ @graph.theme.should equal(Scruffy::Themes::Mephisto)
59
+ end
60
+
61
+ it "should accept a new default type" do
62
+ @graph.default_type = :line
63
+ @graph.default_type.should equal(:line)
64
+ end
65
+
66
+ it "should accept new point markers" do
67
+ markers = ['Jan', 'Feb', 'Mar']
68
+ @graph.point_markers = markers
69
+ @graph.point_markers.should equal(markers)
70
+ end
71
+
72
+ it "should accept a new renderer" do
73
+ renderer = blank_renderer
74
+ @graph.renderer = renderer
75
+ @graph.renderer.should equal(renderer)
76
+ end
77
+
78
+ it "should not accept renderers with missing #render methods" do
79
+ lambda { @graph.renderer = 1 }.should raise_error(ArgumentError)
80
+ end
81
+ end
82
+
83
+ describe "A Scruffy::Graph's initialization block" do
84
+ include CustomRenderers
85
+
86
+ it "should accept just a default_type Symbol" do
87
+ lambda { Scruffy::Graph.new(:line) }.should_not raise_error
88
+ end
89
+
90
+ it "should accept just an options hash" do
91
+ lambda { Scruffy::Graph.new({:title => "My Title"}) }.should_not raise_error
92
+ lambda { Scruffy::Graph.new(:title => "My Title", :theme => Scruffy::Themes::Keynote) }.should_not raise_error
93
+ end
94
+
95
+ it "should accept both a default_type and options hash" do
96
+ lambda {
97
+ Scruffy::Graph.new(:line, {:title => "My Title"})
98
+ Scruffy::Graph.new(:line, :title => "My Title")
99
+ }.should_not raise_error
100
+ end
101
+
102
+ it "should reject any invalid argument combination" do
103
+ lambda { Scruffy::Graph.new({:title => "My Title"}, :line) }.should raise_error(ArgumentError)
104
+ lambda { Scruffy::Graph.new(:line, {:title => "My Title"}, "Any additional arguments.") }.should raise_error(ArgumentError)
105
+ lambda { Scruffy::Graph.new(:line, "Any additional arguments.") }.should raise_error(ArgumentError)
106
+ end
107
+
108
+ it "should reject any options that are not supported" do
109
+ lambda { Scruffy::Graph.new(:title => "My Title", :some_key => "Some Value") }.should raise_error(ArgumentError)
110
+ end
111
+
112
+ it "should successfully save all valid options" do
113
+ options = {:title => "My Title",
114
+ :theme => {:background => [:black],
115
+ :colors => [:red => 'red', :yellow => 'yellow']},
116
+ :layers => [ Scruffy::Layers::Line.new(:points => [100, 200, 300]) ],
117
+ :default_type => :average,
118
+ :value_formatter => Scruffy::Formatters::Currency.new,
119
+ :point_markers => ['One Hundred', 'Two Hundred', 'Three Hundred']}
120
+
121
+ @graph = Scruffy::Graph.new(options)
122
+
123
+ @graph.title.should == options[:title]
124
+ @graph.theme.should == options[:theme]
125
+ @graph.layers.should == options[:layers]
126
+ @graph.default_type.should == options[:default_type]
127
+ @graph.value_formatter.should == options[:value_formatter]
128
+ @graph.point_markers.should == options[:point_markers]
129
+ end
130
+ end
131
+
132
+
133
+ context "A fully populated Graph" do
134
+ setup do
135
+ FileUtils.rm_f File.dirname(__FILE__) + '/*.png'
136
+ FileUtils.rm_f File.dirname(__FILE__) + '/*.jpg'
137
+
138
+ @graph = Scruffy::Graph.new :title => 'Test Graph'
139
+ @graph << Scruffy::Layers::Average.new(:title => 'Average', :points => @graph.layers)
140
+ @graph.layers.first.relevant_data = false
141
+ @graph << Scruffy::Layers::AllSmiles.new(:title => 'Smiles', :points => [100, 200, 300])
142
+ @graph << Scruffy::Layers::Area.new(:title => 'Area', :points => [100, 200, 300])
143
+ @graph << Scruffy::Layers::Bar.new(:title => 'Bar', :points => [100, 200, 300])
144
+ @graph << Scruffy::Layers::Line.new(:title => 'Line', :points => [100, 200, 300])
145
+ end
146
+
147
+ it "should render to SVG" do
148
+ @graph.render(:width => 800).should be_instance_of(String)
149
+ end
150
+
151
+ it "should rasterize to PNG" do
152
+ lambda {
153
+ #@graph.render(:width => 800, :as => 'PNG', :to => outfile('test_graph.png'))
154
+ }.should_not raise_error
155
+ end
156
+
157
+ it "should rasterize to JPG" do
158
+ lambda {
159
+ #@graph.render(:width => 800, :as => 'JPG', :to => outfile('test_graph.jpg'))
160
+ }.should_not raise_error
161
+ end
162
+ end
163
+
164
+
165
+ context "A graph with hash data" do
166
+ specify "should render identically to a graph with array data" do
167
+ @hashgraph = Scruffy::Graph.new :title => 'Graph'
168
+ @hashgraph.add(:line, 'Data', { 0 => 1, 1 => 2, 3 => 4 })
169
+
170
+ @arraygraph = Scruffy::Graph.new :title => 'Graph'
171
+ @arraygraph.add(:line, 'Data', [1, 2, nil, 4])
172
+
173
+ @hashgraph.render(:to => outfile('hash.svg')).should == @arraygraph.render(:to => outfile('array.svg'))
174
+ end
175
+ end
@@ -0,0 +1,30 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
2
+ require 'scruffy'
3
+
4
+ context "Any layer" do
5
+ specify "should accept but ignore nil data" do
6
+ render([100, nil, 300]).should eql([[0.0, 400], [400.0, 0.0]])
7
+ end
8
+
9
+ specify "should accept hash data as sequentially-keyed data" do
10
+ render([100, nil, 300]).should eql([[0.0, 400], [400.0, 0.0]])
11
+ render({0 => 100, 2 => 300}).should eql([[0.0, 400], [400.0, 0.0]])
12
+ end
13
+
14
+ def render points
15
+ layer = Scruffy::Layers::Base.new(:title => 'My base Layer', :points => points)
16
+
17
+ #stub out draw to just return coords
18
+ class << layer; def draw(svg, coords, options={}); coords end; end;
19
+
20
+ coords = []
21
+
22
+ lambda {
23
+ size = [400,400]
24
+ coords = layer.render(Scruffy::Renderers::Base.new.render(:layers => [layer], :size => size),
25
+ :size => size, :min_value => 100, :max_value => 300)
26
+ }.should_not raise_error
27
+
28
+ coords
29
+ end
30
+ end
@@ -1,9 +1,10 @@
1
- context "A Line layer" do
1
+ describe "A Line layer" do
2
2
  setup do
3
3
  @layer = Scruffy::Layers::Line.new(:title => 'My Line Layer', :points => [100, 200, 300])
4
4
 
5
5
  svg = mock('svg')
6
6
  svg.should_receive(:polyline).once
7
7
  svg.should_receive(:circle).exactly(3).times
8
+
8
9
  end
9
10
  end
@@ -0,0 +1,8 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ def outfile( name )
4
+ output_dir = File.join(File.dirname(__FILE__), "output")
5
+
6
+ FileUtils.mkdir( output_dir ) unless File.exist?( output_dir )
7
+ File.join( output_dir, name )
8
+ end
@@ -0,0 +1,34 @@
1
+ desc 'Release the website and new gem version'
2
+ task :deploy => [:check_version, :website, :release] do
3
+ puts "Remember to create SVN tag:"
4
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
5
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
6
+ puts "Suggested comment:"
7
+ puts "Tagging release #{CHANGES}"
8
+ end
9
+
10
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
11
+ task :local_deploy => [:website_generate, :install_gem]
12
+
13
+ task :check_version do
14
+ unless ENV['VERSION']
15
+ puts 'Must pass a VERSION=x.y.z release version'
16
+ exit
17
+ end
18
+ unless ENV['VERSION'] == VERS
19
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
20
+ exit
21
+ end
22
+ end
23
+
24
+ desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
+ task :install_gem_no_doc => [:clean, :package] do
26
+ sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
27
+ end
28
+
29
+ namespace :manifest do
30
+ desc 'Recreate Manifest.txt to include ALL files'
31
+ task :refresh do
32
+ `rake check_manifest | patch -p0 > Manifest.txt`
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ task :ruby_env do
2
+ RUBY_APP = if RUBY_PLATFORM =~ /java/
3
+ "jruby"
4
+ else
5
+ "ruby"
6
+ end unless defined? RUBY_APP
7
+ end
@@ -0,0 +1,17 @@
1
+ desc 'Generate website files'
2
+ task :website_generate => :ruby_env do
3
+ (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
4
+ sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
5
+ end
6
+ end
7
+
8
+ desc 'Upload website files to rubyforge'
9
+ task :website_upload do
10
+ host = "#{rubyforge_username}@rubyforge.org"
11
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
12
+ local_dir = 'website'
13
+ sh %{rsync -rlgoDCv #{local_dir}/ #{host}:#{remote_dir}}
14
+ end
15
+
16
+ desc 'Generate and upload website files'
17
+ task :website => [:website_generate, :website_upload, :publish_docs]
@@ -0,0 +1,101 @@
1
+ require 'test/unit'
2
+ require 'scruffy'
3
+
4
+ class SimpleTheme < Scruffy::Themes::Base
5
+ def initialize
6
+ super({
7
+ :background => [:white, :white],
8
+ :marker => :black,
9
+ :colors => %w(blue green red orange yellow purple pink),
10
+ :stroke_color => 'white'
11
+ })
12
+ end
13
+ end
14
+
15
+ class GraphCreationTest < Test::Unit::TestCase
16
+ BASE_DIR = File.dirname(__FILE__)
17
+ WEBSITE_DIR = BASE_DIR + "/../website/images/graphs"
18
+
19
+ def test_create_pie
20
+ graph = Scruffy::Graph.new
21
+ graph.title = "Favourite Snacks"
22
+ graph.renderer = Scruffy::Renderers::Pie.new
23
+
24
+ graph.add :pie, '', {
25
+ 'Apple' => 20,
26
+ 'Banana' => 100,
27
+ 'Orange' => 70,
28
+ 'Taco' => 30
29
+ }
30
+
31
+ graph.render :to => "#{WEBSITE_DIR}/pie_test.svg"
32
+ graph.render :width => 400, :to => "#{WEBSITE_DIR}/pie_test.png", :as => 'png'
33
+ end
34
+
35
+ def test_create_line
36
+ graph = Scruffy::Graph.new
37
+ graph.title = "Sample Line Graph"
38
+ graph.renderer = Scruffy::Renderers::Standard.new
39
+
40
+ graph.add :line, 'Example', [20, 100, 70, 30, 106]
41
+
42
+ graph.render :to => "#{WEBSITE_DIR}/line_test.svg"
43
+ graph.render :width => 400, :to => "#{WEBSITE_DIR}/line_test.png", :as => 'png'
44
+ end
45
+
46
+
47
+ def test_create_bar
48
+ graph = Scruffy::Graph.new
49
+ graph.title = "Sample Bar Graph"
50
+ graph.renderer = Scruffy::Renderers::Standard.new
51
+ graph.add :bar, 'Example', [20, 100, 70, 30, 106]
52
+ graph.render :to => "#{WEBSITE_DIR}/bar_test.svg"
53
+ graph.render :width => 400, :to => "#{WEBSITE_DIR}/bar_test.png", :as => 'png'
54
+ end
55
+
56
+ def test_split
57
+ graph = Scruffy::Graph.new
58
+ graph.title = "Long-term Comparisons"
59
+ graph.value_formatter = Scruffy::Formatters::Currency.new(:special_negatives => true, :negative_color => '#ff7777')
60
+ graph.renderer = Scruffy::Renderers::Split.new(:split_label => 'Northeastern (Top) / Central (Bottom)')
61
+
62
+ graph.add :area, 'Jeff', [20, -5, 100, 70, 30, 106, 203, 100, 50, 203, 289, 20], :category => :top
63
+ graph.add :area, 'Jerry', [-10, 70, 20, 102, 201, 26, 30, 106, 203, 100, 50, 39], :category => :top
64
+ graph.add :bar, 'Jack', [30, 0, 49, 29, 100, 203, 70, 20, 102, 201, 26, 130], :category => :bottom
65
+ graph.add :line, 'Brasten', [42, 10, 75, 150, 130, 70, -10, -20, 50, 92, -21, 19], :categories => [:top, :bottom]
66
+ graph.add :line, 'Jim', [-10, -20, 50, 92, -21, 56, 92, 84, 82, 100, 39, 120], :categories => [:top, :bottom]
67
+ graph.point_markers = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
68
+
69
+ graph.render :to => "#{WEBSITE_DIR}/split_test.svg"
70
+ graph.render :width => 500, :to => "#{WEBSITE_DIR}/split_test.png", :as => 'png'
71
+ end
72
+
73
+ def test_stacking
74
+ graph = Scruffy::Graph.new
75
+ graph.title = "Comparative Agent Performance"
76
+ graph.value_formatter = Scruffy::Formatters::Percentage.new(:precision => 0)
77
+ graph.add :stacked do |stacked|
78
+ stacked.add :bar, 'Jack', [30, 60, 49, 29, 100, 120]
79
+ stacked.add :bar, 'Jill', [120, 240, 0, 100, 140, 20]
80
+ stacked.add :bar, 'Hill', [10, 10, 90, 20, 40, 10]
81
+ end
82
+ graph.point_markers = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
83
+ graph.render :to => "#{WEBSITE_DIR}/stacking_test.svg"
84
+ graph.render :width => 500, :to => "#{WEBSITE_DIR}/stacking_test.png", :as => 'png'
85
+ end
86
+
87
+ def test_multi_layered
88
+ graph = Scruffy::Graph.new
89
+ graph.title = "Some Kind of Information"
90
+ graph.renderer = Scruffy::Renderers::Cubed.new
91
+
92
+ graph.add :area, 'Jeff', [20, -5, 100, 70, 30, 106], :categories => [:top_left, :bottom_right]
93
+ graph.add :area, 'Jerry', [-10, 70, 20, 102, 201, 26], :categories => [:bottom_left, :buttom_right]
94
+ graph.add :bar, 'Jack', [30, 0, 49, 29, 100, 203], :categories => [:bottom_left, :top_right]
95
+ graph.add :line, 'Brasten', [42, 10, 75, 150, 130, 70], :categories => [:top_right, :bottom_left]
96
+ graph.add :line, 'Jim', [-10, -20, 50, 92, -21, 56], :categories => [:top_left, :bottom_right]
97
+ graph.point_markers = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
98
+ graph.render :to => "#{WEBSITE_DIR}/multi_test.svg"
99
+ graph.render :width => 500, :to => "#{WEBSITE_DIR}/multi_test.png", :as => 'png'
100
+ end
101
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/scruffy'
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestScruffy < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
2
+ <html><head>
3
+ <title>404 Not Found</title>
4
+ </head><body>
5
+ <h1>Not Found</h1>
6
+ <p>The requested URL /images/blank.gif was not found on this server.</p>
7
+ </body></html>
@@ -0,0 +1,71 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <?DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" type=""?>
3
+ <svg xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="360" xmlns="http://www.w3.org/2000/svg">
4
+ <g id="scruffy_graph">
5
+ <g transform="translate(0.0, 0.0)" id="background">
6
+ <defs>
7
+ <linearGradient x2="0%" y2="100%" x1="0%" id="BackgroundGradient" y1="0%">
8
+ <stop stop-color="black" offset="5%"/>
9
+ <stop stop-color="#4A465A" offset="95%"/>
10
+ </linearGradient>
11
+ </defs>
12
+ <rect width="600.0" x="0" y="0" height="360.0" fill="url(#BackgroundGradient)"/>
13
+ </g>
14
+ <g transform="translate(30.0, 7.2)" id="title">
15
+ <text class="title" font-size="25.2" x="270.0" text-anchor="middle" y="25.2" stroke="none" stroke-width="0" fill="white">Sample Bar Graph</text>
16
+ </g>
17
+ <g transform="translate(12.0, 93.6)" id="view">
18
+ <g>
19
+ <g transform="translate(0.0, 4.752)" id="values">
20
+ <text font-size="16.91712" x="96.12" text-anchor="end" y="211.464" fill="white">7</text>
21
+ <text font-size="16.91712" x="96.12" text-anchor="end" y="158.598" fill="white">32</text>
22
+ <text font-size="16.91712" x="96.12" text-anchor="end" y="105.732" fill="white">57</text>
23
+ <text font-size="16.91712" x="96.12" text-anchor="end" y="52.866" fill="white">81</text>
24
+ <text font-size="16.91712" x="96.12" text-anchor="end" y="0.0" fill="white">106</text>
25
+ </g>
26
+ <g transform="translate(106.8, 0.0)" id="grid">
27
+ <line x2="427.2" y2="0.0" x1="0" style="stroke: white; stroke-width: 2;" y1="0.0"/>
28
+ <line x2="427.2" y2="52.866" x1="0" style="stroke: white; stroke-width: 2;" y1="52.866"/>
29
+ <line x2="427.2" y2="105.732" x1="0" style="stroke: white; stroke-width: 2;" y1="105.732"/>
30
+ <line x2="427.2" y2="158.598" x1="0" style="stroke: white; stroke-width: 2;" y1="158.598"/>
31
+ <line x2="427.2" y2="211.464" x1="0" style="stroke: white; stroke-width: 2;" y1="211.464"/>
32
+ </g>
33
+ <g transform="translate(106.8, 218.592)" id="labels">
34
+ </g>
35
+ <g transform="translate(106.8, 0.0)" id="graphs">
36
+ <g class="graph_layer" id="component_graphs_graph_0">
37
+ <g transform="translate(-1.05732, -1.05732)">
38
+ <rect width="79.01064" x="4.272" y="183.881739130435" height="29.6969008695652" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
39
+ <rect width="79.01064" x="5.32932" y="188.111019130435" height="26.5249408695652" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
40
+ </g>
41
+ <rect width="76.896" x="4.272" y="183.881739130435" height="27.5822608695652" fill="#6886B4" style="opacity: 1.0; stroke: none;"/>
42
+ <g transform="translate(-1.05732, -1.05732)">
43
+ <rect width="79.01064" x="89.712" y="12.8289585439838" height="200.749681456016" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
44
+ <rect width="79.01064" x="90.76932" y="17.0582385439838" height="197.577721456016" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
45
+ </g>
46
+ <rect width="76.896" x="89.712" y="12.8289585439838" height="198.635041456016" fill="#6886B4" style="opacity: 1.0; stroke: none;"/>
47
+ <g transform="translate(-1.05732, -1.05732)">
48
+ <rect width="79.01064" x="175.152" y="76.973751263903" height="136.604888736097" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
49
+ <rect width="79.01064" x="176.20932" y="81.203031263903" height="133.432928736097" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
50
+ </g>
51
+ <rect width="76.896" x="175.152" y="76.973751263903" height="134.490248736097" fill="#6886B4" style="opacity: 1.0; stroke: none;"/>
52
+ <g transform="translate(-1.05732, -1.05732)">
53
+ <rect width="79.01064" x="260.592" y="162.500141557128" height="51.0784984428716" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
54
+ <rect width="79.01064" x="261.64932" y="166.729421557128" height="47.9065384428716" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
55
+ </g>
56
+ <rect width="76.896" x="260.592" y="162.500141557128" height="48.9638584428716" fill="#6886B4" style="opacity: 1.0; stroke: none;"/>
57
+ <g transform="translate(-1.05732, -1.05732)">
58
+ <rect width="79.01064" x="346.032" y="0.0" height="213.57864" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
59
+ <rect width="79.01064" x="347.08932" y="4.22928" height="210.40668" style="fill: black; fill-opacity: 0.15; stroke: none;"/>
60
+ </g>
61
+ <rect width="76.896" x="346.032" y="0.0" height="211.464" fill="#6886B4" style="opacity: 1.0; stroke: none;"/>
62
+ </g>
63
+ </g>
64
+ </g>
65
+ </g>
66
+ <g transform="translate(30.0, 46.8)" id="legend">
67
+ <rect width="10.8" x="226.8" y="0" height="10.8" fill="#6886B4"/>
68
+ <text font-size="1.3824" x="228.528" y="1.0368" fill="white" style="color: white">Example</text>
69
+ </g>
70
+ </g>
71
+ </svg>