texel-gchart 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt ADDED
@@ -0,0 +1,43 @@
1
+ == 0.5.0 (2008-04-17)
2
+
3
+ * Support for Map charts
4
+ * Support for Sparkline charts
5
+ * Initial support for Google-o-meter
6
+
7
+ == UNRELEASED
8
+
9
+ * Freeze GChart::VERSION.
10
+
11
+ == 0.4.2 (2008-01-09)
12
+
13
+ * Encoding a flatlined chart doesn't asplode [Jack Danger Canty]
14
+
15
+ == 0.4.1 (2008-01-02)
16
+
17
+ * (bug #16756 fixed) Example in the README is incorrect
18
+
19
+ == 0.4.0 (2007-12-28)
20
+
21
+ * New committer, Abhay Kumar
22
+ * Implement all three encodings. Fix extended encoding calculation.
23
+ * Support bar thickness/spacing for bar charts
24
+ * (bug #16565 fixed) GChart now tells you when your chart is too big.
25
+ * Pushed some bar chart params logic down where it belongs
26
+ * Enforce pie chart spec: pie charts only take one set of data
27
+
28
+ == 0.3.0 (2007-12-24)
29
+
30
+ * Breaking change: labels --> legend
31
+ * Switched to RSpec, added skeletal specs for all types
32
+ * Extensive refactoring, pulled chart types into GChart::Base subclasses
33
+ * (bug) Errors in the static helpers should report a reasonable file and line
34
+
35
+ == 0.2.0 (2007-12-12)
36
+
37
+ * Support for basic :labels
38
+ * Support for pie3d
39
+ * Minor doc cleanups
40
+
41
+ == 0.1.0 (2007-12-10)
42
+
43
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,31 @@
1
+ CHANGELOG.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/gchart.rb
6
+ lib/gchart/bar.rb
7
+ lib/gchart/base.rb
8
+ lib/gchart/line.rb
9
+ lib/gchart/map.rb
10
+ lib/gchart/meter.rb
11
+ lib/gchart/pie.rb
12
+ lib/gchart/pie_3d.rb
13
+ lib/gchart/scatter.rb
14
+ lib/gchart/sparkline.rb
15
+ lib/gchart/venn.rb
16
+ lib/gchart/xy_line.rb
17
+ lib/version.rb
18
+ spec/gchart/bar_spec.rb
19
+ spec/gchart/base_spec.rb
20
+ spec/gchart/line_spec.rb
21
+ spec/gchart/map_spec.rb
22
+ spec/gchart/meter_spec.rb
23
+ spec/gchart/pie_3d_spec.rb
24
+ spec/gchart/pie_spec.rb
25
+ spec/gchart/scatter_spec.rb
26
+ spec/gchart/sparkline_spec.rb
27
+ spec/gchart/venn_spec.rb
28
+ spec/gchart/xy_line_spec.rb
29
+ spec/gchart_spec.rb
30
+ spec/helper.rb
31
+ spec/spec.opts
data/README.txt ADDED
@@ -0,0 +1,81 @@
1
+ = GChart
2
+
3
+ == DESCRIPTION
4
+
5
+ GChart exposes the Google Chart API (http://code.google.com/apis/chart) via
6
+ a friendly Ruby interface. It can generate the URL for a given chart
7
+ (for webpage use), or download the generated PNG (for offline use).
8
+
9
+ == PROBLEMS/TODO
10
+
11
+ * Add support fills (area or background), grid lines, shape markers, range markers
12
+ * Support shorthand colors and color names
13
+ * Make venn data specification friendlier
14
+
15
+ There are lots of missing features. Until they're implemented, you can directly specify
16
+ query parameters using the :extras key, e.g.,
17
+
18
+ # provides a legend for each data set
19
+ g = GChart.line(:data => [[1, 2], [3, 4]], :extras => { "chdl" => "First|Second"})
20
+
21
+ == SYNOPSIS
22
+
23
+ # line chart
24
+ g = GChart.line(:data => [0, 10, 100])
25
+
26
+ # bar chart
27
+ g = GChart.bar(:data => [100, 1000, 10000])
28
+
29
+ # pie chart (pie3d for a fancier look)
30
+ g = GChart.pie(:data => [33, 33, 34])
31
+
32
+ # venn diagram (asize, bsize, csize, ab%, bc%, ca%, abc%)
33
+ g = GChart.venn(:data => [100, 80, 60, 30, 30, 30, 10])
34
+
35
+ # scatter plot (x coords, y coords [, sizes])
36
+ g = GChart.scatter(:data => [[1, 2, 3, 4, 5], [5, 4, 3, 2, 1], [1, 2, 3, 4, 5]])
37
+
38
+ # map chart
39
+ g = GChart.map(:area => 'usa', :data => {'NY'=>1,'VA'=>3,'CA'=>2})
40
+
41
+ # meter
42
+ g = GChart.meter(:data => 70, :label => "70%")
43
+
44
+ # chart title
45
+ g = GChart.line(:title => "Awesomeness over Time", :data => [0, 10, 100])
46
+
47
+ # data set legend
48
+ g = GChart.line(:data => [[1, 2], [3, 4]], :legend => ["Monkeys", "Ferrets"])
49
+
50
+ # data set colors
51
+ g = GChart.line(:data => [[0, 10, 100], [100, 10, 0]], :colors => ["ff0000", "0000ff"])
52
+
53
+ g.to_url # generate the chart's URL, or
54
+ g.fetch # get the bytes, or
55
+ g.write("foo.png") # write to a file (defaults to "chart.png")
56
+ g.write(stream) # write to anything that quacks like IO
57
+
58
+ == LICENSE
59
+
60
+ (The MIT License)
61
+
62
+ Copyright 2007-2008 John Barnette (jbarnette@rubyforge.org)
63
+
64
+ Permission is hereby granted, free of charge, to any person obtaining
65
+ a copy of this software and associated documentation files (the
66
+ 'Software'), to deal in the Software without restriction, including
67
+ without limitation the rights to use, copy, modify, merge, publish,
68
+ distribute, sublicense, and/or sell copies of the Software, and to
69
+ permit persons to whom the Software is furnished to do so, subject to
70
+ the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be
73
+ included in all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
76
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
78
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
79
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
80
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
81
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require "rubygems"
2
+ require "hoe"
3
+ require "spec/rake/spectask"
4
+
5
+ require "./lib/version.rb"
6
+
7
+ hoe = Hoe.new("gchart", GChart::VERSION) do |p|
8
+ p.rubyforge_name = "gchart"
9
+ p.author = "John Barnette"
10
+ p.email = "jbarnette@rubyforge.org"
11
+ p.summary = "GChart uses the Google Chart API to create pretty pictures."
12
+ p.description = p.paragraphs_of("README.txt", 2..5).join("\n\n")
13
+ p.url = "http://gchart.rubyforge.org"
14
+ p.changes = p.paragraphs_of("CHANGELOG.txt", 0..1).join("\n\n")
15
+ end
16
+
17
+ desc "Run all specs"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_files = FileList["spec/**/*_spec.rb"]
20
+ t.spec_opts = ["--options", "spec/spec.opts"]
21
+ end
22
+
23
+ desc "Run all specs and get coverage statistics"
24
+ Spec::Rake::SpecTask.new('spec:rcov') do |t|
25
+ t.spec_files = FileList["spec/**/*_spec.rb"]
26
+ t.rcov = true
27
+ t.spec_opts = ["--options", "spec/spec.opts"]
28
+ end
29
+
30
+ Rake::Task[:default].prerequisites.clear
31
+ task :default => :spec
data/lib/gchart.rb ADDED
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/version")
2
+
3
+ %w(base bar line map meter pie pie_3d scatter sparkline venn xy_line).each do |type|
4
+ require File.expand_path(File.dirname(__FILE__) + "/gchart/#{type}")
5
+ end
6
+
7
+ module GChart
8
+ URL = "http://chart.apis.google.com/chart"
9
+ SIMPLE_CHARS = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a
10
+ EXTENDED_CHARS = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + %w[- .]
11
+ EXTENDED_PAIRS = EXTENDED_CHARS.collect { |first| EXTENDED_CHARS.collect { |second| first + second } }.flatten
12
+
13
+ class << self
14
+ # Convenience constructor for GChart::Line.
15
+ def line(*args, &block); Line.new(*args, &block) end
16
+
17
+ # Convenience constructor for GChart::XYLine.
18
+ def xyline(*args, &block); XYLine.new(*args, &block) end
19
+
20
+ # Convenience constructor for GChart::Bar.
21
+ def bar(*args, &block); Bar.new(*args, &block) end
22
+
23
+ # Convenience constructor for GChart::Map.
24
+ def map(*args, &block); Map.new(*args, &block) end
25
+
26
+ # Convenience constructor for GChart::Meter.
27
+ def meter(*args, &block); Meter.new(*args, &block) end
28
+
29
+ # Convenience constructor for GChart::Pie.
30
+ def pie(*args, &block); Pie.new(*args, &block) end
31
+
32
+ # Convenience constructor for GChart::Pie3D.
33
+ def pie3d(*args, &block); Pie3D.new(*args, &block) end
34
+
35
+ # Convenience constructor for GChart::Line.
36
+ def sparkline(*args, &block); Sparkline.new(*args, &block) end
37
+
38
+ # Convenience constructor for GChart::Venn.
39
+ def venn(*args, &block); Venn.new(*args, &block) end
40
+
41
+ # Convenience constructor for GChart::Scatter.
42
+ def scatter(*args, &block); Scatter.new(*args, &block) end
43
+
44
+ # Encode +n+ as a string. +n+ is normalized based on +max+.
45
+ # +encoding+ can currently only be :extended.
46
+ def encode(encoding, n, max)
47
+ case encoding
48
+ when :simple
49
+ return "_" if n.nil?
50
+ SIMPLE_CHARS[((n/max.to_f) * (SIMPLE_CHARS.size - 1)).round]
51
+ when :text
52
+ return "-1" if n.nil?
53
+ ((((n/max.to_f) * 1000.0).round)/10.0).to_s
54
+ when :extended
55
+ return "__" if n.nil?
56
+ EXTENDED_PAIRS[max.zero? ? 0 : ((n/max.to_f) * (EXTENDED_PAIRS.size - 1)).round]
57
+ else
58
+ raise ArgumentError, "unsupported encoding: #{encoding.inspect}"
59
+ end
60
+ end
61
+ end
62
+ end
data/lib/gchart/bar.rb ADDED
@@ -0,0 +1,60 @@
1
+ module GChart
2
+ class Bar < GChart::Base
3
+ ORIENTATIONS = [:horizontal, :vertical]
4
+
5
+ attr_accessor :grouped
6
+ alias_method :grouped?, :grouped
7
+
8
+ attr_reader :orientation
9
+
10
+ attr_reader :thickness
11
+ attr_reader :spacing
12
+
13
+ def initialize(*args, &block)
14
+ @grouped = false
15
+ @orientation = :horizontal
16
+ super
17
+ end
18
+
19
+ def orientation=(orientation)
20
+ unless ORIENTATIONS.include?(orientation)
21
+ raise ArgumentError, "Invalid orientation: #{orientation.inspect}. " +
22
+ "Valid orientations: #{ORIENTATIONS.inspect}"
23
+ end
24
+
25
+ @orientation = orientation
26
+ end
27
+
28
+ def horizontal?
29
+ @orientation == :horizontal
30
+ end
31
+
32
+ def vertical?
33
+ @orientation == :vertical
34
+ end
35
+
36
+ def thickness=(thickness)
37
+ raise ArgumentError, "Invalid thickness: #{thickness.inspect}" if thickness.nil? || thickness < 1
38
+ @thickness = thickness
39
+ end
40
+
41
+ def spacing=(spacing)
42
+ raise ArgumentError, "Invalid spacing: #{spacing.inspect}" if spacing.nil? || spacing < 1
43
+ @spacing = spacing
44
+ end
45
+
46
+ # overrides GChart::Base#query_params
47
+ def query_params(params={}) #:nodoc:
48
+ values = []
49
+ values << thickness if thickness
50
+ values << spacing if thickness && spacing
51
+
52
+ params["chbh"] = values.join(",") unless values.empty?
53
+ super(params)
54
+ end
55
+
56
+ def render_chart_type #:nodoc:
57
+ "b#{@orientation.to_s[0..0]}#{grouped? ? "g" : "s"}"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,133 @@
1
+ require "open-uri"
2
+ require "uri"
3
+
4
+ module GChart
5
+ class Base
6
+ # Array of chart data. See subclasses for specific usage.
7
+ attr_accessor :data
8
+
9
+ # Hash of additional HTTP query params.
10
+ attr_accessor :extras
11
+
12
+ # Chart title.
13
+ attr_accessor :title
14
+
15
+ # Array of rrggbb colors, one per data set.
16
+ attr_accessor :colors
17
+
18
+ # Array of legend text, one per data set.
19
+ attr_accessor :legend
20
+
21
+ # Max data value for quantization.
22
+ attr_accessor :max
23
+
24
+ # Chart width, in pixels.
25
+ attr_reader :width
26
+
27
+ # Chart height, in pixels.
28
+ attr_reader :height
29
+
30
+ def initialize(options={}, &block)
31
+ @data = []
32
+ @extras = {}
33
+ @width = 300
34
+ @height = 200
35
+
36
+ options.each { |k, v| send("#{k}=", v) }
37
+ yield(self) if block_given?
38
+ end
39
+
40
+ # Sets the chart's width, in pixels. Raises +ArgumentError+
41
+ # if +width+ is less than 1 or greater than 1,000.
42
+ def width=(width)
43
+ if width.nil? || width < 1 || width > 1_000
44
+ raise ArgumentError, "Invalid width: #{width.inspect}"
45
+ end
46
+
47
+ @width = width
48
+ end
49
+
50
+ # Sets the chart's height, in pixels. Raises +ArgumentError+
51
+ # if +height+ is less than 1 or greater than 1,000.
52
+ def height=(height)
53
+ if height.nil? || height < 1 || height > 1_000
54
+ raise ArgumentError, "Invalid height: #{height.inspect}"
55
+ end
56
+
57
+ @height = height
58
+ end
59
+
60
+ # Returns the chart's size as "WIDTHxHEIGHT".
61
+ def size
62
+ "#{width}x#{height}"
63
+ end
64
+
65
+ # Sets the chart's size as "WIDTHxHEIGHT". Raises +ArgumentError+
66
+ # if +width+ * +height+ is greater than 300,000 pixels.
67
+ def size=(size)
68
+ self.width, self.height = size.split("x").collect { |n| Integer(n) }
69
+
70
+ if (width * height) > 300_000
71
+ raise ArgumentError, "Invalid size: #{size.inspect} yields a graph with more than 300,000 pixels"
72
+ end
73
+ end
74
+
75
+ # Returns the chart's URL.
76
+ def to_url
77
+ query = query_params.collect { |k, v| "#{k}=#{URI.escape(v)}" }.join("&")
78
+ "#{GChart::URL}?#{query}"
79
+ end
80
+
81
+ # Returns the chart's generated PNG as a blob.
82
+ def fetch
83
+ open(to_url) { |io| io.read }
84
+ end
85
+
86
+ # Writes the chart's generated PNG to a file. If +io_or_file+ quacks like an IO,
87
+ # calls +write+ on it instead.
88
+ def write(io_or_file="chart.png")
89
+ return io_or_file.write(fetch) if io_or_file.respond_to?(:write)
90
+ open(io_or_file, "w+") { |io| io.write(fetch) }
91
+ end
92
+
93
+ protected
94
+
95
+ def query_params(raw_params={}) #:nodoc:
96
+ params = raw_params.merge("cht" => render_chart_type, "chs" => size)
97
+
98
+ render_data(params)
99
+ render_title(params)
100
+ render_colors(params)
101
+ render_legend(params)
102
+
103
+ params.merge(extras)
104
+ end
105
+
106
+ def render_chart_type #:nodoc:
107
+ raise NotImplementedError, "override in subclasses"
108
+ end
109
+
110
+ def render_data(params) #:nodoc:
111
+ raw = data && data.first.is_a?(Array) ? data : [data]
112
+ max = self.max || raw.collect { |s| s.max }.max
113
+
114
+ sets = raw.collect do |set|
115
+ set.collect { |n| GChart.encode(:extended, n, max) }.join
116
+ end
117
+
118
+ params["chd"] = "e:#{sets.join(",")}"
119
+ end
120
+
121
+ def render_title(params) #:nodoc:
122
+ params["chtt"] = title.tr("\n ", "|+") if title
123
+ end
124
+
125
+ def render_colors(params) #:nodoc:
126
+ params["chco"] = colors.join(",") if colors
127
+ end
128
+
129
+ def render_legend(params) #:nodoc:
130
+ params["chdl"] = legend.join("|") if legend
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,7 @@
1
+ module GChart
2
+ class Line < GChart::Base
3
+ def render_chart_type #:nodoc:
4
+ "lc"
5
+ end
6
+ end
7
+ end
data/lib/gchart/map.rb ADDED
@@ -0,0 +1,71 @@
1
+ module GChart
2
+ class Map < GChart::Base
3
+ AREAS = %w[africa asia europe middle_east south_america usa world]
4
+ attr_accessor :area
5
+ attr_accessor :area_codes
6
+ attr_accessor :background
7
+
8
+ def initialize(*args, &block)
9
+ super(*args, &block)
10
+ # Set some sane defaults so that the only requirement is data
11
+ @area = 'world' #default
12
+ @background = 'dfdfff' #make it look like water
13
+ @colors = ['ffffff','f8fcf8','006c00']
14
+ #Set the maximum size for maps (this is a better default because
15
+ # it is also the proper aspect ratio)
16
+ @width = '440'
17
+ @height = '220'
18
+ end
19
+
20
+ # Map data can be in the form {"VA'=>5,'NY'=>1} or [['VA',5],['NY',1]]
21
+ # Raises +ArgumentError+ if data does not fit these forms.
22
+ def data=(data)
23
+ if data.is_a?(Array) && data.any?{ |pair| pair.size != 2 }
24
+ raise ArgumentError, "Data array must contain [area],[value] pairs"
25
+ end
26
+ # 'unzip' the data into separate arrays
27
+ area_data, values = data.to_a.transpose
28
+
29
+ # Reject malformed area codes
30
+ if area_data.any?{ |code| code !~ /^\w\w$/}
31
+ raise ArgumentError, "Area data must have exactly two characters"
32
+ end
33
+ @area_codes = area_data.join.upcase
34
+ super(values)
35
+ end
36
+
37
+ def render_chart_type #:nodoc:
38
+ "t"
39
+ end
40
+
41
+ def area=(area)
42
+ raise ArgumentError unless AREAS.include? area
43
+ @area = area
44
+ end
45
+
46
+ # overrides GChart::Base#query_params
47
+ def query_params(params={}) #:nodoc:
48
+ params["chtm"] = area unless area.empty?
49
+ params["chld"] = area_codes if area_codes
50
+ params["chf"] = "bg,s,#{@background}" if @background
51
+ super(params)
52
+ end
53
+
54
+ # overrides GChart::Base#render_data
55
+ def render_data(params)
56
+ super(params)
57
+ # Maps require at least one data point. Add a "missing value".
58
+ # It may be better to refactor the base class.
59
+ params["chd"] << '__' if params["chd"] =~ /e:$/
60
+ end
61
+
62
+ def render_title(params) #:nodoc:
63
+ nil #N/A for map
64
+ end
65
+
66
+ def render_legend(params) #:nodoc:
67
+ nil #N/A for map
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,29 @@
1
+ module GChart
2
+ class Meter < GChart::Base
3
+ attr_accessor :label
4
+
5
+ def render_chart_type #:nodoc:
6
+ "gom"
7
+ end
8
+
9
+ # The data for a meter is a single data point expressed as a percent
10
+ def render_data(params)
11
+ value = data.is_a?(Array) ? data.flatten.first : data
12
+ params["chd"] = "t:#{value.to_f}"
13
+ end
14
+
15
+ def label=(string)
16
+ return if string.nil?
17
+ if (string.is_a?(Array) && string.size > 1) or string.include?("|")
18
+ raise ArgumentError, "Meter can only have one label"
19
+ end
20
+ @label = string.to_s
21
+ end
22
+
23
+ # Commandeer render_legend to render the label
24
+ def render_legend(params)
25
+ self.label = legend if self.label.nil? # Can use legend instead of label
26
+ params["chl"] = label if label
27
+ end
28
+ end
29
+ end
data/lib/gchart/pie.rb ADDED
@@ -0,0 +1,21 @@
1
+ module GChart
2
+ class Pie < GChart::Base
3
+ # A single array of chart data. Raises +ArgumentError+
4
+ # if more than one data set is provided.
5
+ def data=(data)
6
+ if data.is_a?(Array) and data.first.is_a?(Array) and data.size > 1
7
+ raise ArgumentError, "Pie charts only have one data set"
8
+ end
9
+
10
+ super(data)
11
+ end
12
+
13
+ def render_chart_type #:nodoc:
14
+ "p"
15
+ end
16
+
17
+ def render_legend(params) #:nodoc:
18
+ params["chl"] = legend.join("|") if legend
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module GChart
2
+ class Pie3D < GChart::Pie
3
+ def render_chart_type #:nodoc:
4
+ "p3"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module GChart
2
+ class Scatter < GChart::Base
3
+ def render_chart_type #:nodoc:
4
+ "s"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module GChart
2
+ class Sparkline < GChart::Base
3
+ # Sparklines are essentially the same as line charts, but without
4
+ # axis lines. Because they are often placed within text, the default
5
+ # size should be smaller.
6
+ def initialize(*args, &block)
7
+ super(*args, &block)
8
+ @width = "60"
9
+ @height = "20"
10
+ end
11
+ def render_chart_type #:nodoc:
12
+ "ls"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module GChart
2
+ class Venn < GChart::Base
3
+ def render_chart_type #:nodoc:
4
+ "v"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module GChart
2
+ class XYLine < GChart::Base
3
+ def render_chart_type #:nodoc:
4
+ "lxy"
5
+ end
6
+ end
7
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module GChart
2
+ VERSION = "0.5.0".freeze
3
+ end
@@ -0,0 +1,80 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Bar do
4
+ before(:each) do
5
+ @chart = GChart::Bar.new
6
+ end
7
+
8
+ it "is ungrouped by default" do
9
+ @chart.grouped.should == false
10
+ @chart.should_not be_grouped
11
+ end
12
+
13
+ it "is horizontal by default" do
14
+ @chart.orientation.should == :horizontal
15
+ @chart.should be_horizontal
16
+ @chart.should_not be_vertical
17
+ end
18
+
19
+ it "renders the correct chart type" do
20
+ GChart::Bar.new.render_chart_type.should == "bhs"
21
+ GChart::Bar.new(:grouped => true).render_chart_type.should == "bhg"
22
+ GChart::Bar.new(:orientation => :vertical).render_chart_type.should == "bvs"
23
+ end
24
+ end
25
+
26
+ describe GChart::Bar, "#orientation" do
27
+ before(:each) { @chart = GChart::Bar.new }
28
+
29
+ it "complains if orientation is invalid" do
30
+ lambda { @chart.orientation = :monkey }.should raise_error(ArgumentError)
31
+ end
32
+ end
33
+
34
+ describe GChart::Bar, "#thickness" do
35
+ before(:each) { @chart = GChart::Bar.new }
36
+
37
+ it "can be specified" do
38
+ @chart.thickness = 10
39
+ @chart.thickness.should == 10
40
+ end
41
+
42
+ it "complains about negative numbers" do
43
+ lambda { @chart.thickness = -1 }.should raise_error(ArgumentError)
44
+ end
45
+ end
46
+
47
+ describe GChart::Bar, "#spacing" do
48
+ before(:each) { @chart = GChart::Bar.new }
49
+
50
+ it "can be specified" do
51
+ @chart.spacing = 2
52
+ @chart.spacing.should == 2
53
+ end
54
+
55
+ it "complains about negative numbers" do
56
+ lambda { @chart.spacing = -1 }.should raise_error(ArgumentError)
57
+ end
58
+ end
59
+
60
+ describe GChart::Bar, "#query_params" do
61
+ before(:each) { @chart = GChart::Bar.new }
62
+
63
+ it "contains the chart's type" do
64
+ @chart.query_params["cht"].should =~ /b(h|v)(g|s)/
65
+ end
66
+
67
+ it "contains the chart's bar height" do
68
+ @chart.thickness = 10
69
+ @chart.query_params.keys.include?("chbh").should be_true
70
+ @chart.query_params["chbh"].should == "10"
71
+ @chart.spacing = 2
72
+ @chart.query_params.keys.include?("chbh").should be_true
73
+ @chart.query_params["chbh"].should == "10,2"
74
+ end
75
+
76
+ it "it does not contain a bar height without a thickness" do
77
+ @chart.spacing = 2
78
+ @chart.query_params.keys.include?("chbh").should be_false
79
+ end
80
+ end
@@ -0,0 +1,156 @@
1
+ require "tmpdir"
2
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
3
+
4
+ describe GChart::Base do
5
+ it "can be initialized with a hash" do
6
+ GChart::Base.new(:title => "foo").title.should == "foo"
7
+ end
8
+
9
+ it "complains about being initialized with unknown attributes" do
10
+ lambda { GChart::Base.new(:monkey => :chimchim) }.should raise_error(NoMethodError)
11
+ end
12
+
13
+ it "can be initialized with a block" do
14
+ chart = GChart::Base.new do |c|
15
+ c.title = "foo"
16
+ end
17
+
18
+ chart.title.should == "foo"
19
+ end
20
+ end
21
+
22
+ describe GChart::Base, "#data" do
23
+ it "is an empty array by default" do
24
+ GChart::Base.new.data.should == []
25
+ end
26
+ end
27
+
28
+ describe GChart::Base, "#size" do
29
+ before(:each) { @chart = GChart::Base.new }
30
+
31
+ it "can be accessed as width and height" do
32
+ @chart.width.should_not be_zero
33
+ @chart.height.should_not be_zero
34
+ end
35
+
36
+ it "can be accessed as a combined size" do
37
+ @chart.size.should == "#{@chart.width}x#{@chart.height}"
38
+ end
39
+
40
+ it "can be specified as a combined size" do
41
+ @chart.size = "11x13"
42
+ @chart.width.should == 11
43
+ @chart.height.should == 13
44
+ end
45
+
46
+ it "has a reasonable default value" do
47
+ @chart.size.should == "300x200"
48
+ end
49
+
50
+ it "complains about negative numbers" do
51
+ lambda { @chart.size = "-15x13" }.should raise_error(ArgumentError)
52
+ lambda { @chart.width = -1 }.should raise_error(ArgumentError)
53
+ lambda { @chart.height= -1 }.should raise_error(ArgumentError)
54
+ end
55
+
56
+ it "complains about sizes that are out of bounds (300,000 pixel graph limit, 1000 pixel side limit)" do
57
+ lambda { @chart.size = "491x611" }.should raise_error(ArgumentError)
58
+ lambda { @chart.size = "1001x300" }.should raise_error(ArgumentError)
59
+ lambda { @chart.size = "300x1001" }.should raise_error(ArgumentError)
60
+ end
61
+ end
62
+
63
+ describe GChart::Base, "#render_chart_type" do
64
+ it "raises; subclasses must implement" do
65
+ lambda { GChart::Base.new.render_chart_type }.should raise_error(NotImplementedError)
66
+ end
67
+ end
68
+
69
+ describe GChart::Base, "#query_params" do
70
+ before(:each) do
71
+ @chart = GChart::Base.new
72
+ @chart.stub!(:render_chart_type).and_return("TEST")
73
+ end
74
+
75
+ it "contains the chart's type" do
76
+ @chart.query_params["cht"].should == "TEST"
77
+ end
78
+
79
+ it "contains the chart's data" do
80
+ @chart.data = [[1, 2, 3], [3, 2, 1]]
81
+ @chart.query_params["chd"].should == "e:VVqq..,..qqVV"
82
+ end
83
+
84
+ it "contains the chart's size" do
85
+ @chart.query_params["chs"].should == "300x200"
86
+ end
87
+
88
+ it "contains the chart's title" do
89
+ @chart.title = "foo"
90
+ @chart.query_params["chtt"].should == "foo"
91
+ end
92
+
93
+ it "escapes the chart's title" do
94
+ @chart.title = "foo bar"
95
+ @chart.query_params["chtt"].should == "foo+bar"
96
+
97
+ @chart.title = "foo\nbar"
98
+ @chart.query_params["chtt"].should == "foo|bar"
99
+ end
100
+
101
+ it "contains the chart's colors" do
102
+ @chart.colors = ["cccccc", "eeeeee"]
103
+ @chart.query_params["chco"].should == "cccccc,eeeeee"
104
+ end
105
+ end
106
+
107
+ describe GChart::Base, "#to_url" do
108
+ before(:each) do
109
+ @chart = GChart::Base.new
110
+ @chart.stub!(:render_chart_type).and_return("TEST")
111
+ end
112
+
113
+ it "generates a URL that points at Google" do
114
+ @chart.to_url.should =~ %r(http://chart.apis.google.com/chart)
115
+ end
116
+ end
117
+
118
+ describe GChart::Base, "#fetch" do
119
+ # THIS EXPECTATION HITS THE CLOUD! Comment it out for a faster cycle. :)
120
+ it "fetches a blob from Google" do
121
+ blob = GChart.line(:data => [1, 2]).fetch
122
+ blob.should_not be_nil
123
+ blob.should =~ /PNG/
124
+ end
125
+ end
126
+
127
+ describe GChart::Base, "#write" do
128
+ before(:each) do
129
+ @chart = GChart::Base.new
130
+ @chart.stub!(:fetch).and_return("PAYLOAD")
131
+ end
132
+
133
+ it "writes to chart.png by default" do
134
+ Dir.chdir(Dir.tmpdir) do
135
+ @chart.write
136
+ File.file?("chart.png").should == true
137
+ end
138
+ end
139
+
140
+ it "writes to a specified file" do
141
+ Dir.chdir(Dir.tmpdir) do
142
+ @chart.write("foo.png")
143
+ File.file?("foo.png").should == true
144
+ end
145
+ end
146
+
147
+ it "writes to anything that quacks like IO" do
148
+ result = ""
149
+
150
+ StringIO.open(result, "w+") do |io|
151
+ @chart.write(io)
152
+ end
153
+
154
+ result.should == "PAYLOAD"
155
+ end
156
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Line do
4
+ it "renders the correct chart type" do
5
+ GChart::Line.new.render_chart_type.should == "lc"
6
+ end
7
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Map do
4
+ before(:each) { @chart = GChart::Map.new }
5
+
6
+ it "initializes to a default area of 'world'" do
7
+ @chart.area.should == 'world'
8
+ end
9
+
10
+ it "defaults to maximum size of 440x220" do
11
+ @chart.size.should == '440x220'
12
+ end
13
+
14
+ it "renders the correct chart type" do
15
+ @chart.render_chart_type.should == "t"
16
+ end
17
+ end
18
+
19
+ describe GChart::Map, "#query_params" do
20
+ before(:each) { @chart = GChart::Map.new }
21
+
22
+ it "contains the chart's type" do
23
+ @chart.query_params["cht"].should == "t"
24
+ end
25
+
26
+ it "contains the map's area" do
27
+ @chart.area = "usa"
28
+ @chart.query_params.keys.include?("chtm").should be_true
29
+ @chart.query_params["chtm"].should == "usa"
30
+ end
31
+
32
+ it "defaults to a blank map" do
33
+ @chart.query_params["chd"].should =~ /^[es]:__?/
34
+ end
35
+
36
+ it "checks for a valid area" do
37
+ lambda { @chart.area = 'usa' }.should_not raise_error(ArgumentError)
38
+ lambda { @chart.area = 'mars' }.should raise_error(ArgumentError)
39
+ end
40
+
41
+ it "makes sure the areas have one value" do
42
+ @chart.data = [['NY',1],['VA',2],['WY',3]]
43
+ @chart.area_codes.length.should == @chart.data.size * 2
44
+ end
45
+ end
46
+
47
+ describe GChart::Map, "#data" do
48
+ it "accepts data as a hash or pair of arrays" do
49
+ lambda { GChart::Map.new(:data => {"VA"=>5}) }.should_not raise_error(ArgumentError)
50
+ lambda { GChart::Map.new(:data => {"VA"=>5, "NY"=>1}) }.should_not raise_error(ArgumentError)
51
+ lambda { GChart::Map.new(:data => [["VA",5],["NY",1]]) }.should_not raise_error(ArgumentError)
52
+ lambda { GChart::Map.new(:data => [["VA","NY"],[5,1]]) }.should raise_error(ArgumentError)
53
+ lambda { GChart::Map.new(:data => [1, 2, 3]) }.should raise_error(ArgumentError)
54
+ lambda { GChart::Map.new(:data => [[1, 2, 3]]) }.should raise_error(ArgumentError)
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Meter do
4
+ it "renders the correct chart type" do
5
+ GChart::Meter.new.render_chart_type.should == "gom"
6
+ end
7
+ end
8
+
9
+ describe GChart::Meter, "#query_params" do
10
+ before(:each) do
11
+ @meter = GChart::Meter.new
12
+ @meter.data = 50
13
+ end
14
+ it "encodes the data correctly" do
15
+ for data in [70, 70.0, "70", "70.0", "70%"] do
16
+ @meter.data = data
17
+ @meter.query_params["chd"].should == "t:70.0"
18
+ end
19
+ end
20
+ it "allows a label" do
21
+ @meter.label = "Label"
22
+ @meter.query_params.keys.include?("chl").should be_true
23
+ @meter.query_params["chl"].should == "Label"
24
+ end
25
+ it "allows a legend" do
26
+ @meter.legend = "Legend"
27
+ @meter.query_params.keys.include?("chl").should be_true
28
+ @meter.query_params["chl"].should == "Legend"
29
+ end
30
+ it "makes label take precedence over legend" do
31
+ @meter.legend = "Legend"
32
+ @meter.label = "Label"
33
+ @meter.query_params.keys.include?("chl").should be_true
34
+ @meter.query_params["chl"].should == "Label"
35
+ end
36
+ it "complains about more than one label" do
37
+ lambda { @meter.label = "set1" }.should_not raise_error(ArgumentError)
38
+ lambda { @meter.label = ["set1"] }.should_not raise_error(ArgumentError)
39
+ lambda { @meter.label = "set1|set2" }.should raise_error(ArgumentError)
40
+ lambda { @meter.label = ['set1','set2'] }.should raise_error(ArgumentError)
41
+ end
42
+ end
43
+
44
+ describe GChart::Map, "#render_data" do
45
+ it "allows only one data point" do
46
+ lambda { @meter.data = "set1" }.should_not raise_error(ArgumentError)
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Pie3D do
4
+ it "renders the correct chart type" do
5
+ GChart::Pie3D.new.render_chart_type.should == "p3"
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Pie do
4
+ it "renders the correct chart type" do
5
+ GChart::Pie.new.render_chart_type.should == "p"
6
+ end
7
+ end
8
+
9
+ describe GChart::Pie, "#query_params" do
10
+ before(:each) { @chart = GChart::Pie.new }
11
+
12
+ it "contains the chart's type" do
13
+ @chart.query_params["cht"].should == "p"
14
+ end
15
+
16
+ it "contains the chart's legend" do
17
+ @chart.legend = ["foo"]
18
+ @chart.query_params.keys.include?("chl").should be_true
19
+ @chart.query_params["chl"].should == "foo"
20
+ end
21
+ end
22
+
23
+ describe GChart::Pie, "#data" do
24
+ it "complains if you provide more than one set of data" do
25
+ lambda { GChart::Pie.new(:data => [1, 2, 3]) }.should_not raise_error(ArgumentError)
26
+ lambda { GChart::Pie.new(:data => [[1, 2, 3]]) }.should_not raise_error(ArgumentError)
27
+ lambda { GChart::Pie.new(:data => [[1, 2, 3], [3, 2, 1]]) }.should raise_error(ArgumentError)
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Scatter do
4
+ it "renders the correct chart type" do
5
+ GChart::Scatter.new.render_chart_type.should == "s"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Sparkline do
4
+ it "renders the correct chart type" do
5
+ GChart::Sparkline.new.render_chart_type.should == "ls"
6
+ end
7
+
8
+ it "defaults to 60x20" do
9
+ GChart::Sparkline.new.size.should == "60x20"
10
+ end
11
+ end
12
+
@@ -0,0 +1,7 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::Venn do
4
+ it "renders the correct chart type" do
5
+ GChart::Venn.new.render_chart_type.should == "v"
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe GChart::XYLine do
4
+ it "renders the correct chart type" do
5
+ GChart::XYLine.new.render_chart_type.should == "lxy"
6
+ end
7
+ end
@@ -0,0 +1,69 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/helper")
2
+
3
+ describe GChart do
4
+ it "supplies a version" do
5
+ GChart::VERSION.should_not be_nil
6
+ end
7
+ end
8
+
9
+ describe GChart, ".encode" do
10
+ it "supports the simple, text, and extended encoding" do
11
+ lambda { GChart.encode(:simple, 4, 10) }.should_not raise_error(ArgumentError)
12
+ lambda { GChart.encode(:text, 4, 10) }.should_not raise_error(ArgumentError)
13
+ lambda { GChart.encode(:extended, 4, 10) }.should_not raise_error(ArgumentError)
14
+ lambda { GChart.encode(:monkey, 4, 10) }.should raise_error(ArgumentError)
15
+ end
16
+
17
+ it "implements the simple encoding" do
18
+ expected = {
19
+ 0 => "A", 19 => "T", 27 => "b", 53 => "1", 61 => "9",
20
+ 12 => "M", 39 => "n", 57 => "5", 45 => "t", 51 => "z"
21
+ }
22
+
23
+ expected.each do |original, encoded|
24
+ GChart.encode(:simple, original, 61).should == encoded
25
+ end
26
+ end
27
+
28
+ it "implements the text encoding" do
29
+ expected = {
30
+ 0 => "0.0", 10 => "10.0", 58 => "58.0", 95 => "95.0", 30 => "30.0", 8 => "8.0", 63 => "63.0", 100 => "100.0"
31
+ }
32
+
33
+ expected.each do |original, encoded|
34
+ GChart.encode(:text, original, 100).should == encoded
35
+ end
36
+ end
37
+
38
+ it "implements the extended encoding" do
39
+ expected = {
40
+ 0 => "AA", 25 => "AZ", 26 => "Aa", 51 => "Az", 52 => "A0", 61 => "A9", 62 => "A-", 63 => "A.",
41
+ 64 => "BA", 89 => "BZ", 90 => "Ba", 115 => "Bz", 116 => "B0", 125 => "B9", 126 => "B-", 127 => "B.",
42
+ 4032 => ".A", 4057 => ".Z", 4058 => ".a", 4083 => ".z", 4084 => ".0", 4093 => ".9", 4094 => ".-", 4095 => ".."
43
+ }
44
+
45
+ expected.each do |original, encoded|
46
+ GChart.encode(:extended, original, 4095).should == encoded
47
+ end
48
+ end
49
+
50
+ it "encodes nil correctly" do
51
+ GChart.encode(:simple, nil, 1).should == "_"
52
+ GChart.encode(:text, nil, 1).should == "-1"
53
+ GChart.encode(:extended, nil, 1).should == "__"
54
+ end
55
+
56
+ it "encodes 0 with a max of 0 correctly" do
57
+ GChart.encode(:extended, 0, 0).should == "AA"
58
+ end
59
+ end
60
+
61
+ describe GChart, ".line" do
62
+ it "can render a basic line URL" do
63
+ expected = { "cht" => "lc", "chs" => "300x200", "chd" => "e:AAAp..", "chtt" => "test" }
64
+ chart = GChart.line(:title => "test", :data => [1, 100, 10000])
65
+
66
+ chart.query_params.should == expected
67
+ chart.to_url.should == "http://chart.apis.google.com/chart?chs=300x200&cht=lc&chtt=test&chd=e:AAAp.."
68
+ end
69
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.expand_path("#{File.dirname(__FILE__)}/../lib"))
2
+
3
+ require "spec"
4
+ require "gchart"
5
+
6
+ module GChart
7
+ class Base
8
+ public :query_params
9
+ public :render_chart_type, :render_data
10
+ end
11
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,7 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
7
+ --backtrace
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: texel-gchart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - John Barnette
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.3
23
+ version:
24
+ description: "== PROBLEMS/TODO * Add support fills (area or background), grid lines, shape markers, range markers * Support shorthand colors and color names * Make venn data specification friendlier There are lots of missing features. Until they're implemented, you can directly specify query parameters using the :extras key, e.g., # provides a legend for each data set g = GChart.line(:data => [[1, 2], [3, 4]], :extras => { \"chdl\" => \"First|Second\"})"
25
+ email: jbarnette@rubyforge.org
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - CHANGELOG.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - CHANGELOG.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - lib/gchart.rb
40
+ - lib/gchart/bar.rb
41
+ - lib/gchart/base.rb
42
+ - lib/gchart/line.rb
43
+ - lib/gchart/map.rb
44
+ - lib/gchart/meter.rb
45
+ - lib/gchart/pie.rb
46
+ - lib/gchart/pie_3d.rb
47
+ - lib/gchart/scatter.rb
48
+ - lib/gchart/sparkline.rb
49
+ - lib/gchart/venn.rb
50
+ - lib/gchart/xy_line.rb
51
+ - lib/version.rb
52
+ - spec/gchart/bar_spec.rb
53
+ - spec/gchart/base_spec.rb
54
+ - spec/gchart/line_spec.rb
55
+ - spec/gchart/map_spec.rb
56
+ - spec/gchart/meter_spec.rb
57
+ - spec/gchart/pie_3d_spec.rb
58
+ - spec/gchart/pie_spec.rb
59
+ - spec/gchart/scatter_spec.rb
60
+ - spec/gchart/sparkline_spec.rb
61
+ - spec/gchart/venn_spec.rb
62
+ - spec/gchart/xy_line_spec.rb
63
+ - spec/gchart_spec.rb
64
+ - spec/helper.rb
65
+ - spec/spec.opts
66
+ has_rdoc: true
67
+ homepage: http://gchart.rubyforge.org
68
+ post_install_message:
69
+ rdoc_options:
70
+ - --main
71
+ - README.txt
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ requirements: []
87
+
88
+ rubyforge_project: gchart
89
+ rubygems_version: 1.0.1
90
+ signing_key:
91
+ specification_version: 2
92
+ summary: GChart uses the Google Chart API to create pretty pictures.
93
+ test_files: []
94
+