texel-gchart 0.5.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.
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
+