gruff 0.2.6 → 0.2.7
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 +9 -0
- data/Manifest.txt +33 -13
- data/Rakefile +18 -210
- data/assets/city_scene/background/0000.png +0 -0
- data/assets/city_scene/background/0600.png +0 -0
- data/assets/city_scene/background/2000.png +0 -0
- data/assets/city_scene/clouds/cloudy.png +0 -0
- data/assets/city_scene/clouds/partly_cloudy.png +0 -0
- data/assets/city_scene/clouds/stormy.png +0 -0
- data/assets/city_scene/grass/default.png +0 -0
- data/assets/city_scene/haze/true.png +0 -0
- data/assets/city_scene/number_sample/1.png +0 -0
- data/assets/city_scene/number_sample/2.png +0 -0
- data/assets/city_scene/number_sample/default.png +0 -0
- data/assets/city_scene/sky/0000.png +0 -0
- data/assets/city_scene/sky/0200.png +0 -0
- data/assets/city_scene/sky/0400.png +0 -0
- data/assets/city_scene/sky/0600.png +0 -0
- data/assets/city_scene/sky/0800.png +0 -0
- data/assets/city_scene/sky/1000.png +0 -0
- data/assets/city_scene/sky/1200.png +0 -0
- data/assets/city_scene/sky/1400.png +0 -0
- data/assets/city_scene/sky/1500.png +0 -0
- data/assets/city_scene/sky/1700.png +0 -0
- data/assets/city_scene/sky/2000.png +0 -0
- data/assets/pc306715.jpg +0 -0
- data/lib/gruff/base.rb +50 -13
- data/lib/gruff/mini/pie.rb +6 -2
- data/lib/gruff/mini/side_bar.rb +5 -6
- data/lib/gruff/pie.rb +12 -3
- data/lib/gruff/side_bar.rb +48 -42
- data/lib/gruff/side_stacked_bar.rb +1 -0
- data/test/test_bar.rb +13 -1
- data/test/test_mini_side_bar.rb +28 -2
- data/test/test_side_bar.rb +12 -0
- metadata +35 -11
data/CHANGELOG
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
|
3
|
+
== 0.2.7
|
4
|
+
|
5
|
+
* Regenerated Manifest.txt
|
6
|
+
* Added scene sample to package
|
7
|
+
* Added mini side_bar (EXPERIMENTAL)
|
8
|
+
* Added @zero_degree option to Gruff::Pie so first slice can start somewhere other than 3 o'clock
|
9
|
+
* Increased size of numbers in Gruff::Mini::Pie
|
10
|
+
* Added legend_box_size accessor
|
11
|
+
|
3
12
|
== 0.2.6
|
4
13
|
|
5
14
|
* Fixed missing side_bar.rb in Manifest.txt
|
data/Manifest.txt
CHANGED
@@ -1,9 +1,31 @@
|
|
1
1
|
CHANGELOG
|
2
|
-
|
2
|
+
Manifest.txt
|
3
3
|
MIT-LICENSE
|
4
4
|
Rakefile
|
5
|
-
|
6
|
-
|
5
|
+
README.txt
|
6
|
+
assets/pc306715.jpg
|
7
|
+
assets/city_scene/background/0000.png
|
8
|
+
assets/city_scene/background/0600.png
|
9
|
+
assets/city_scene/background/2000.png
|
10
|
+
assets/city_scene/clouds/cloudy.png
|
11
|
+
assets/city_scene/clouds/partly_cloudy.png
|
12
|
+
assets/city_scene/clouds/stormy.png
|
13
|
+
assets/city_scene/grass/default.png
|
14
|
+
assets/city_scene/haze/true.png
|
15
|
+
assets/city_scene/number_sample/1.png
|
16
|
+
assets/city_scene/number_sample/2.png
|
17
|
+
assets/city_scene/number_sample/default.png
|
18
|
+
assets/city_scene/sky/0000.png
|
19
|
+
assets/city_scene/sky/0200.png
|
20
|
+
assets/city_scene/sky/0400.png
|
21
|
+
assets/city_scene/sky/0600.png
|
22
|
+
assets/city_scene/sky/0800.png
|
23
|
+
assets/city_scene/sky/1000.png
|
24
|
+
assets/city_scene/sky/1200.png
|
25
|
+
assets/city_scene/sky/1400.png
|
26
|
+
assets/city_scene/sky/1500.png
|
27
|
+
assets/city_scene/sky/1700.png
|
28
|
+
assets/city_scene/sky/2000.png
|
7
29
|
lib/gruff.rb
|
8
30
|
lib/gruff/area.rb
|
9
31
|
lib/gruff/bar.rb
|
@@ -15,31 +37,29 @@ lib/gruff/net.rb
|
|
15
37
|
lib/gruff/photo_bar.rb
|
16
38
|
lib/gruff/pie.rb
|
17
39
|
lib/gruff/scene.rb
|
40
|
+
lib/gruff/side_bar.rb
|
18
41
|
lib/gruff/side_stacked_bar.rb
|
19
42
|
lib/gruff/spider.rb
|
20
43
|
lib/gruff/stacked_bar.rb
|
21
|
-
lib/gruff/side_bar.rb
|
22
|
-
|
23
44
|
lib/gruff/mini/bar.rb
|
45
|
+
lib/gruff/mini/legend.rb
|
24
46
|
lib/gruff/mini/pie.rb
|
25
47
|
lib/gruff/mini/side_bar.rb
|
26
|
-
|
27
|
-
|
48
|
+
test/gruff_test_case.rb
|
49
|
+
test/output
|
28
50
|
test/test_area.rb
|
29
51
|
test/test_bar.rb
|
30
52
|
test/test_base.rb
|
31
|
-
test/gruff_test_case.rb
|
32
53
|
test/test_legend.rb
|
33
54
|
test/test_line.rb
|
55
|
+
test/test_mini_bar.rb
|
56
|
+
test/test_mini_pie.rb
|
57
|
+
test/test_mini_side_bar.rb
|
34
58
|
test/test_net.rb
|
35
|
-
test/output
|
36
59
|
test/test_photo.rb
|
37
60
|
test/test_pie.rb
|
38
61
|
test/test_scene.rb
|
62
|
+
test/test_side_bar.rb
|
39
63
|
test/test_sidestacked_bar.rb
|
40
64
|
test/test_spider.rb
|
41
65
|
test/test_stacked_bar.rb
|
42
|
-
|
43
|
-
test/test_mini_bar.rb
|
44
|
-
test/test_mini_pie.rb
|
45
|
-
test/test_mini_side_bar.rb
|
data/Rakefile
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
require 'rubygems'
|
3
2
|
require 'hoe'
|
4
3
|
$:.unshift(File.dirname(__FILE__) + "/lib")
|
@@ -12,216 +11,25 @@ Hoe.new('Gruff', Gruff::VERSION) do |p|
|
|
12
11
|
p.summary = "Beautiful graphs for one or multiple datasets."
|
13
12
|
p.url = "http://nubyonrails.com/pages/gruff"
|
14
13
|
p.clean_globs = ['test/output/*.png']
|
14
|
+
end
|
15
15
|
|
16
|
-
|
16
|
+
desc "Simple test on packaged files to make sure they are all there"
|
17
|
+
task :verify => :package do
|
18
|
+
# An error message will be displayed if files are missing
|
19
|
+
if system %(ruby -e "require 'pkg/gruff-#{Gruff::VERSION}/lib/gruff'")
|
20
|
+
puts "\nThe library files are present"
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
24
|
+
##
|
25
|
+
# Catch unmatched tasks and run them as a unit test.
|
26
|
+
#
|
27
|
+
# Makes it possible to do
|
28
|
+
#
|
29
|
+
# rake pie
|
30
|
+
#
|
31
|
+
# To run the +test/test_pie+ file.
|
19
32
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# require 'rake/packagetask'
|
24
|
-
# require 'rake/gempackagetask'
|
25
|
-
# require 'rake/contrib/rubyforgepublisher'
|
26
|
-
#
|
27
|
-
# $:.unshift(File.dirname(__FILE__) + "/lib")
|
28
|
-
# require 'gruff'
|
29
|
-
#
|
30
|
-
# PKG_NAME = 'gruff'
|
31
|
-
# PKG_VERSION = Gruff::VERSION
|
32
|
-
# PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
33
|
-
#
|
34
|
-
# RELEASE_NAME = "REL #{PKG_VERSION}"
|
35
|
-
#
|
36
|
-
# RUBY_FORGE_PROJECT = "gruff"
|
37
|
-
# RUBY_FORGE_USER = "topfunky"
|
38
|
-
#
|
39
|
-
# desc "Default Task"
|
40
|
-
# task :default => [ :clean, :test ]
|
41
|
-
#
|
42
|
-
# desc "Clean images generated by tests"
|
43
|
-
# task :clean do
|
44
|
-
# rm FileList['test/output/*.png']
|
45
|
-
# rm_rf 'pkg'
|
46
|
-
# rm_rf 'doc'
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
# desc "Copy documentation to topfunky.com"
|
50
|
-
# task :rdoc_deploy => [:rdoc] do
|
51
|
-
# dirs = %w{doc}
|
52
|
-
# onserver = "topfunky@topfunky.com:/home/topfunky/topfunky.com/clients/rails/gruff"
|
53
|
-
# dirs.each do | dir|
|
54
|
-
# `rsync -avz -e ssh "#{`pwd`.chomp}/#{dir}" "#{onserver}" --exclude ".svn"`
|
55
|
-
# end
|
56
|
-
# end
|
57
|
-
#
|
58
|
-
# # Run the unit tests
|
59
|
-
# Rake::TestTask.new { |t|
|
60
|
-
# t.libs << "test"
|
61
|
-
# t.pattern = 'test/*_test.rb'
|
62
|
-
# t.verbose = true
|
63
|
-
# }
|
64
|
-
#
|
65
|
-
# # Genereate the RDoc documentation
|
66
|
-
# Rake::RDocTask.new { |rdoc|
|
67
|
-
# rdoc.rdoc_dir = 'doc'
|
68
|
-
# rdoc.title = "Gruff -- Beautiful graphs"
|
69
|
-
# # rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
|
70
|
-
# rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
71
|
-
# rdoc.rdoc_files.include('README', 'CHANGELOG')
|
72
|
-
# rdoc.rdoc_files.include('lib/gruff.rb')
|
73
|
-
# rdoc.rdoc_files.include('lib/gruff/*.rb')
|
74
|
-
# }
|
75
|
-
#
|
76
|
-
#
|
77
|
-
# # Create compressed packages
|
78
|
-
# spec = Gem::Specification.new do |s|
|
79
|
-
# s.platform = Gem::Platform::RUBY
|
80
|
-
# s.name = PKG_NAME
|
81
|
-
# s.summary = "Beautiful graphs for one or multiple datasets."
|
82
|
-
# s.description = %q{Make colorful graphs for use on websites or documents.}
|
83
|
-
# s.version = PKG_VERSION
|
84
|
-
#
|
85
|
-
# s.author = "Geoffrey Grosenbach"
|
86
|
-
# s.email = "boss@topfunky.com"
|
87
|
-
# s.rubyforge_project = RUBY_FORGE_PROJECT
|
88
|
-
# s.homepage = "http://www.topfunky.com"
|
89
|
-
#
|
90
|
-
# s.has_rdoc = true
|
91
|
-
# s.requirements << 'none'
|
92
|
-
# s.require_path = 'lib'
|
93
|
-
# s.autorequire = 'gruff'
|
94
|
-
#
|
95
|
-
# s.files = [ "Rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
|
96
|
-
# s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
97
|
-
# s.files = s.files + Dir.glob( "assets/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
98
|
-
# s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) || item.include?("\.png") }
|
99
|
-
# end
|
100
|
-
#
|
101
|
-
# Rake::GemPackageTask.new(spec) do |p|
|
102
|
-
# p.gem_spec = spec
|
103
|
-
# p.need_tar = true
|
104
|
-
# p.need_zip = true
|
105
|
-
# end
|
106
|
-
#
|
107
|
-
# desc "Publish the API documentation"
|
108
|
-
# task :pgem => [:package] do
|
109
|
-
# Rake::SshFilePublisher.new("boss@topfunky.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
110
|
-
# end
|
111
|
-
#
|
112
|
-
# desc "Publish the release files to RubyForge."
|
113
|
-
# task :release => [:package] do
|
114
|
-
# files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
|
115
|
-
#
|
116
|
-
# if RUBY_FORGE_PROJECT then
|
117
|
-
# require 'net/http'
|
118
|
-
# require 'open-uri'
|
119
|
-
#
|
120
|
-
# project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
|
121
|
-
# project_data = open(project_uri) { |data| data.read }
|
122
|
-
# group_id = project_data[/[?&]group_id=(\d+)/, 1]
|
123
|
-
# raise "Couldn't get group id" unless group_id
|
124
|
-
#
|
125
|
-
# # This echos password to shell which is a bit sucky
|
126
|
-
# if ENV["RUBY_FORGE_PASSWORD"]
|
127
|
-
# password = ENV["RUBY_FORGE_PASSWORD"]
|
128
|
-
# else
|
129
|
-
# print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
|
130
|
-
# password = STDIN.gets.chomp
|
131
|
-
# end
|
132
|
-
#
|
133
|
-
# login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
134
|
-
# data = [
|
135
|
-
# "login=1",
|
136
|
-
# "form_loginname=#{RUBY_FORGE_USER}",
|
137
|
-
# "form_pw=#{password}"
|
138
|
-
# ].join("&")
|
139
|
-
# http.post("/account/login.php", data)
|
140
|
-
# end
|
141
|
-
#
|
142
|
-
# cookie = login_response["set-cookie"]
|
143
|
-
# raise "Login failed" unless cookie
|
144
|
-
# headers = { "Cookie" => cookie }
|
145
|
-
#
|
146
|
-
# release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
|
147
|
-
# release_data = open(release_uri, headers) { |data| data.read }
|
148
|
-
# package_id = release_data[/[?&]package_id=(\d+)/, 1]
|
149
|
-
# raise "Couldn't get package id" unless package_id
|
150
|
-
#
|
151
|
-
# first_file = true
|
152
|
-
# release_id = ""
|
153
|
-
#
|
154
|
-
# files.each do |filename|
|
155
|
-
# basename = File.basename(filename)
|
156
|
-
# file_ext = File.extname(filename)
|
157
|
-
# file_data = File.open(filename, "rb") { |file| file.read }
|
158
|
-
#
|
159
|
-
# puts "Releasing #{basename}..."
|
160
|
-
#
|
161
|
-
# release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
162
|
-
# release_date = Time.now.strftime("%Y-%m-%d %H:%M")
|
163
|
-
# type_map = {
|
164
|
-
# ".zip" => "3000",
|
165
|
-
# ".tgz" => "3110",
|
166
|
-
# ".gz" => "3110",
|
167
|
-
# ".gem" => "1400"
|
168
|
-
# }; type_map.default = "9999"
|
169
|
-
# type = type_map[file_ext]
|
170
|
-
# boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
|
171
|
-
#
|
172
|
-
# query_hash = if first_file then
|
173
|
-
# {
|
174
|
-
# "group_id" => group_id,
|
175
|
-
# "package_id" => package_id,
|
176
|
-
# "release_name" => RELEASE_NAME,
|
177
|
-
# "release_date" => release_date,
|
178
|
-
# "type_id" => type,
|
179
|
-
# "processor_id" => "8000", # Any
|
180
|
-
# "release_notes" => "",
|
181
|
-
# "release_changes" => "",
|
182
|
-
# "preformatted" => "1",
|
183
|
-
# "submit" => "1"
|
184
|
-
# }
|
185
|
-
# else
|
186
|
-
# {
|
187
|
-
# "group_id" => group_id,
|
188
|
-
# "release_id" => release_id,
|
189
|
-
# "package_id" => package_id,
|
190
|
-
# "step2" => "1",
|
191
|
-
# "type_id" => type,
|
192
|
-
# "processor_id" => "8000", # Any
|
193
|
-
# "submit" => "Add This File"
|
194
|
-
# }
|
195
|
-
# end
|
196
|
-
#
|
197
|
-
# query = "?" + query_hash.map do |(name, value)|
|
198
|
-
# [name, URI.encode(value)].join("=")
|
199
|
-
# end.join("&")
|
200
|
-
#
|
201
|
-
# data = [
|
202
|
-
# "--" + boundary,
|
203
|
-
# "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
|
204
|
-
# "Content-Type: application/octet-stream",
|
205
|
-
# "Content-Transfer-Encoding: binary",
|
206
|
-
# "", file_data, ""
|
207
|
-
# ].join("\x0D\x0A")
|
208
|
-
#
|
209
|
-
# release_headers = headers.merge(
|
210
|
-
# "Content-Type" => "multipart/form-data; boundary=#{boundary}"
|
211
|
-
# )
|
212
|
-
#
|
213
|
-
# target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
|
214
|
-
# http.post(target + query, data, release_headers)
|
215
|
-
# end
|
216
|
-
#
|
217
|
-
# if first_file then
|
218
|
-
# release_id = release_response.body[/release_id=(\d+)/, 1]
|
219
|
-
# raise("Couldn't get release id") unless release_id
|
220
|
-
# end
|
221
|
-
#
|
222
|
-
# first_file = false
|
223
|
-
# end
|
224
|
-
# end
|
225
|
-
# end
|
226
|
-
#
|
227
|
-
#
|
33
|
+
rule '' do |t|
|
34
|
+
system "ruby test/test_#{t.name}.rb"
|
35
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/assets/pc306715.jpg
ADDED
Binary file
|
data/lib/gruff/base.rb
CHANGED
@@ -20,7 +20,7 @@ require File.dirname(__FILE__) + '/deprecated'
|
|
20
20
|
|
21
21
|
module Gruff
|
22
22
|
|
23
|
-
VERSION = '0.2.
|
23
|
+
VERSION = '0.2.7'
|
24
24
|
|
25
25
|
class Base
|
26
26
|
|
@@ -124,6 +124,12 @@ module Gruff
|
|
124
124
|
# Experimental
|
125
125
|
attr_accessor :stacked
|
126
126
|
|
127
|
+
|
128
|
+
# Optionally set the size of the colored box by each item in the legend. Default is 20.0
|
129
|
+
#
|
130
|
+
# Will be scaled down if graph is smaller than 800px wide.
|
131
|
+
attr_accessor :legend_box_size
|
132
|
+
|
127
133
|
|
128
134
|
# If one numerical argument is given, the graph is drawn at 4/3 ratio according to the given width (800 results in 800x600, 400 gives 400x300, etc.).
|
129
135
|
#
|
@@ -141,6 +147,21 @@ module Gruff
|
|
141
147
|
@rows = target_width.to_f * 0.75
|
142
148
|
end
|
143
149
|
|
150
|
+
initialize_ivars
|
151
|
+
|
152
|
+
reset_themes
|
153
|
+
theme_keynote
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Set instance variables for this object.
|
158
|
+
#
|
159
|
+
# Subclasses can override this, call super, then set values separately.
|
160
|
+
#
|
161
|
+
# This makes it possible to set defaults in a subclass but still allow
|
162
|
+
# developers to change this values in their program.
|
163
|
+
|
164
|
+
def initialize_ivars
|
144
165
|
# Internal for calculations
|
145
166
|
@raw_columns = 800.0
|
146
167
|
@raw_rows = 800.0 * (@rows/@columns)
|
@@ -162,6 +183,8 @@ module Gruff
|
|
162
183
|
@marker_font_size = 21.0
|
163
184
|
@legend_font_size = 20.0
|
164
185
|
@title_font_size = 36.0
|
186
|
+
|
187
|
+
@legend_box_size = 20.0
|
165
188
|
|
166
189
|
@no_data_message = "No Data"
|
167
190
|
|
@@ -177,9 +200,6 @@ module Gruff
|
|
177
200
|
@y_axis_increment = nil
|
178
201
|
@stacked = nil
|
179
202
|
@norm_data = nil
|
180
|
-
|
181
|
-
reset_themes()
|
182
|
-
theme_keynote()
|
183
203
|
end
|
184
204
|
|
185
205
|
def font=(font_path)
|
@@ -380,7 +400,7 @@ protected
|
|
380
400
|
# Subclasses should start by calling super() for this method.
|
381
401
|
def draw
|
382
402
|
make_stacked if @stacked
|
383
|
-
setup_drawing
|
403
|
+
setup_drawing
|
384
404
|
|
385
405
|
debug {
|
386
406
|
# Outer margin
|
@@ -391,10 +411,13 @@ protected
|
|
391
411
|
}
|
392
412
|
end
|
393
413
|
|
394
|
-
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
414
|
+
##
|
415
|
+
# Calculates size of drawable area and draws the decorations.
|
416
|
+
#
|
417
|
+
# * line markers
|
418
|
+
# * legend
|
419
|
+
# * title
|
420
|
+
|
398
421
|
def setup_drawing
|
399
422
|
# Maybe should be done in one of the following functions for more granularity.
|
400
423
|
unless @has_data
|
@@ -439,6 +462,9 @@ protected
|
|
439
462
|
@spread = @spread > 0 ? @spread : 1
|
440
463
|
end
|
441
464
|
|
465
|
+
##
|
466
|
+
# Calculates size of drawable area, general font dimensions, etc.
|
467
|
+
|
442
468
|
def setup_graph_measurements
|
443
469
|
@marker_caps_height = calculate_caps_height(@marker_font_size)
|
444
470
|
@title_caps_height = calculate_caps_height(@title_font_size)
|
@@ -449,10 +475,19 @@ protected
|
|
449
475
|
@graph_right_margin,
|
450
476
|
@graph_bottom_margin) = [LEFT_MARGIN, RIGHT_MARGIN, BOTTOM_MARGIN]
|
451
477
|
else
|
478
|
+
longest_left_label_width = 0
|
479
|
+
if @has_left_labels
|
480
|
+
longest_left_label_width = calculate_width(@marker_font_size,
|
481
|
+
labels.values.inject('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }) * 1.25
|
482
|
+
else
|
483
|
+
longest_left_label_width = calculate_width(@marker_font_size,
|
484
|
+
label(@maximum_value.to_f))
|
485
|
+
end
|
486
|
+
|
452
487
|
# Shift graph if left line numbers are hidden
|
453
|
-
line_number_width = @hide_line_numbers ?
|
488
|
+
line_number_width = @hide_line_numbers && !@has_left_labels ?
|
454
489
|
0.0 :
|
455
|
-
(
|
490
|
+
(longest_left_label_width + LABEL_MARGIN * 2)
|
456
491
|
|
457
492
|
@graph_left = LEFT_MARGIN +
|
458
493
|
line_number_width +
|
@@ -607,8 +642,7 @@ protected
|
|
607
642
|
|
608
643
|
@legend_labels = @data.collect {|item| item[DATA_LABEL_INDEX] }
|
609
644
|
|
610
|
-
legend_square_width =
|
611
|
-
legend_square_margin = 4
|
645
|
+
legend_square_width = @legend_box_size # small square with color of this item
|
612
646
|
|
613
647
|
# May fix legend drawing problem at small sizes
|
614
648
|
@d.font = @font if @font
|
@@ -886,6 +920,9 @@ private
|
|
886
920
|
end
|
887
921
|
end
|
888
922
|
|
923
|
+
##
|
924
|
+
# Return a formatted string representing a number value that should be printed as a label.
|
925
|
+
|
889
926
|
def label(value)
|
890
927
|
if (@spread.to_f % @marker_count.to_f == 0) || !@y_axis_increment.nil?
|
891
928
|
return value.to_i.to_s
|
data/lib/gruff/mini/pie.rb
CHANGED
@@ -9,14 +9,18 @@ module Gruff
|
|
9
9
|
|
10
10
|
include Gruff::Mini::Legend
|
11
11
|
|
12
|
-
def
|
12
|
+
def initialize_ivars
|
13
|
+
super
|
14
|
+
|
13
15
|
@hide_legend = true
|
14
16
|
@hide_title = true
|
15
17
|
@hide_line_numbers = true
|
16
18
|
|
17
|
-
@marker_font_size =
|
19
|
+
@marker_font_size = 60.0
|
18
20
|
@legend_font_size = 60.0
|
21
|
+
end
|
19
22
|
|
23
|
+
def draw
|
20
24
|
expand_canvas_for_vertical_legend
|
21
25
|
|
22
26
|
super
|
data/lib/gruff/mini/side_bar.rb
CHANGED
@@ -5,18 +5,17 @@
|
|
5
5
|
module Gruff
|
6
6
|
module Mini
|
7
7
|
|
8
|
-
class SideBar < Gruff::
|
8
|
+
class SideBar < Gruff::SideBar
|
9
9
|
|
10
|
-
def
|
10
|
+
def initialize_ivars
|
11
|
+
super
|
11
12
|
@hide_legend = true
|
12
13
|
@hide_title = true
|
13
14
|
@hide_line_numbers = true
|
14
|
-
|
15
|
+
|
15
16
|
@marker_font_size = 40.0
|
16
|
-
super
|
17
|
-
|
18
17
|
end
|
19
|
-
|
18
|
+
|
20
19
|
end
|
21
20
|
|
22
21
|
end
|
data/lib/gruff/pie.rb
CHANGED
@@ -5,6 +5,15 @@ class Gruff::Pie < Gruff::Base
|
|
5
5
|
|
6
6
|
TEXT_OFFSET_PERCENTAGE = 0.15
|
7
7
|
|
8
|
+
# Can be used to make the pie start cutting slices at the top (-90.0)
|
9
|
+
# or at another angle. Default is 0.0, which starts at 3 o'clock.
|
10
|
+
attr_accessor :zero_degree
|
11
|
+
|
12
|
+
def initialize_ivars
|
13
|
+
super
|
14
|
+
@zero_degree = 0.0
|
15
|
+
end
|
16
|
+
|
8
17
|
def draw
|
9
18
|
@hide_line_markers = true
|
10
19
|
|
@@ -18,7 +27,7 @@ class Gruff::Pie < Gruff::Base
|
|
18
27
|
center_x = @graph_left + (@graph_width / 2.0)
|
19
28
|
center_y = @graph_top + (@graph_height / 2.0) - 10 # Move graph up a bit
|
20
29
|
total_sum = sums_for_pie()
|
21
|
-
prev_degrees =
|
30
|
+
prev_degrees = @zero_degree
|
22
31
|
|
23
32
|
# Use full data since we can easily calculate percentages
|
24
33
|
@data.sort{ |a, b| a[DATA_VALUES_INDEX][0] <=> b[DATA_VALUES_INDEX][0] }.each do |data_row|
|
@@ -61,11 +70,11 @@ private
|
|
61
70
|
# labels on the left and right.
|
62
71
|
def draw_label(center_x, center_y, angle, radius, amount)
|
63
72
|
# TODO Don't use so many hard-coded numbers
|
64
|
-
r_offset =
|
73
|
+
r_offset = 20.0 # The distance out from the center of the pie to get point
|
65
74
|
x_offset = center_x # + 15.0 # The label points need to be tweaked slightly
|
66
75
|
y_offset = center_y # This one doesn't though
|
67
76
|
radius_offset = (radius + r_offset)
|
68
|
-
ellipse_factor = radius_offset * 0.
|
77
|
+
ellipse_factor = radius_offset * 0.15
|
69
78
|
x = x_offset + ((radius_offset + ellipse_factor) * Math.cos(angle.deg2rad))
|
70
79
|
y = y_offset + (radius_offset * Math.sin(angle.deg2rad))
|
71
80
|
|
data/lib/gruff/side_bar.rb
CHANGED
@@ -14,6 +14,8 @@ class Gruff::SideBar < Gruff::Base
|
|
14
14
|
|
15
15
|
return if @hide_line_markers
|
16
16
|
|
17
|
+
@d = @d.stroke_antialias false
|
18
|
+
|
17
19
|
# Draw horizontal line markers and annotate with numbers
|
18
20
|
@d = @d.stroke(@marker_color)
|
19
21
|
@d = @d.stroke_width 1
|
@@ -23,38 +25,41 @@ class Gruff::SideBar < Gruff::Base
|
|
23
25
|
increment = significant(@maximum_value.to_f / number_of_lines)
|
24
26
|
(0..number_of_lines).each do |index|
|
25
27
|
|
26
|
-
line_diff
|
27
|
-
x
|
28
|
-
@d
|
29
|
-
|
30
|
-
diff = index - number_of_lines
|
28
|
+
line_diff = (@graph_right - @graph_left) / number_of_lines
|
29
|
+
x = @graph_right - (line_diff * index) - 1
|
30
|
+
@d = @d.line(x, @graph_bottom, x, @graph_top)
|
31
|
+
diff = index - number_of_lines
|
31
32
|
marker_label = diff.abs * increment
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
34
|
+
unless @hide_line_numbers
|
35
|
+
@d.fill = @marker_color
|
36
|
+
@d.font = @font if @font
|
37
|
+
@d.stroke = 'transparent'
|
38
|
+
@d.pointsize = scale_fontsize(@marker_font_size)
|
39
|
+
# @d.gravity = NorthGravity
|
40
|
+
@d = @d.annotate_scaled( @base_image,
|
41
|
+
100, 20,
|
42
|
+
x - (@marker_font_size/1.5), @graph_bottom + 40,
|
43
|
+
marker_label.to_s, @scale)
|
44
|
+
end # unless
|
45
|
+
@d = @d.stroke_antialias true
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
46
|
-
|
49
|
+
##
|
50
|
+
# Draw on the Y axis instead of the X
|
51
|
+
|
47
52
|
def draw_label(y_offset, index)
|
48
53
|
if !@labels[index].nil? && @labels_seen[index].nil?
|
49
|
-
@d.fill
|
50
|
-
@d.font
|
51
|
-
@d.stroke
|
52
|
-
@d.font_weight
|
53
|
-
@d.pointsize
|
54
|
-
@d.gravity
|
55
|
-
@d
|
54
|
+
@d.fill = @marker_color
|
55
|
+
@d.font = @font if @font
|
56
|
+
@d.stroke = 'transparent'
|
57
|
+
@d.font_weight = NormalWeight
|
58
|
+
@d.pointsize = scale_fontsize(@marker_font_size)
|
59
|
+
@d.gravity = EastGravity
|
60
|
+
@d = @d.annotate_scaled(@base_image,
|
56
61
|
1, 1,
|
57
|
-
|
62
|
+
-@graph_left + LABEL_MARGIN * 2.0, y_offset,
|
58
63
|
@labels[index], @scale)
|
59
64
|
@labels_seen[index] = 1
|
60
65
|
end
|
@@ -72,34 +77,35 @@ class Gruff::SideBar < Gruff::Base
|
|
72
77
|
spacing_factor = 0.9
|
73
78
|
|
74
79
|
@bar_width = @graph_height / @column_count.to_f
|
75
|
-
@d
|
76
|
-
height
|
77
|
-
length
|
80
|
+
@d = @d.stroke_opacity 0.0
|
81
|
+
height = Array.new(@column_count, 0)
|
82
|
+
length = Array.new(@column_count, @graph_left)
|
78
83
|
|
79
84
|
@norm_data.each_with_index do |data_row, row_index|
|
80
85
|
@d = @d.fill data_row[DATA_COLOR_INDEX]
|
81
86
|
|
82
87
|
data_row[1].each_with_index do |data_point, point_index|
|
83
88
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
89
|
+
# Using the original calcs from the stacked bar chart
|
90
|
+
# to get the difference between
|
91
|
+
# part of the bart chart we wish to stack.
|
92
|
+
temp1 = @graph_left + (@graph_width -
|
93
|
+
data_point * @graph_width -
|
94
|
+
height[point_index]) + 1
|
95
|
+
temp2 = @graph_left + @graph_width - height[point_index] - 1
|
96
|
+
difference = temp2 - temp1
|
97
|
+
|
98
|
+
left_x = length[point_index] #+ 1
|
99
|
+
left_y = @graph_top + (@bar_width * point_index)
|
100
|
+
right_x = left_x + difference
|
101
|
+
right_y = left_y + @bar_width * spacing_factor
|
102
|
+
length[point_index] += difference
|
97
103
|
height[point_index] += (data_point * @graph_width - 2)
|
98
104
|
|
99
|
-
@d
|
105
|
+
@d = @d.rectangle(left_x, left_y, right_x, right_y)
|
100
106
|
|
101
107
|
# Calculate center based on bar_width and current row
|
102
|
-
label_center
|
108
|
+
label_center = @graph_top + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0)
|
103
109
|
draw_label(label_center, point_index)
|
104
110
|
end
|
105
111
|
|
data/test/test_bar.rb
CHANGED
@@ -112,6 +112,18 @@ class TestGruffBar < GruffTestCase
|
|
112
112
|
g.write("test/output/bar_set_marker.png")
|
113
113
|
end
|
114
114
|
|
115
|
+
def test_set_legend_box_size
|
116
|
+
g = setup_basic_graph(400)
|
117
|
+
g.title = "Set Legend Box Size"
|
118
|
+
g.legend_box_size = 10.0
|
119
|
+
g.write("test/output/bar_set_legend_box_size_sm.png")
|
120
|
+
|
121
|
+
g = setup_basic_graph(400)
|
122
|
+
g.title = "Set Legend Box Size"
|
123
|
+
g.legend_box_size = 50.0
|
124
|
+
g.write("test/output/bar_set_legend_box_size_lg.png")
|
125
|
+
end
|
126
|
+
|
115
127
|
def test_x_y_labels
|
116
128
|
g = setup_basic_graph(400)
|
117
129
|
g.title = "X Y Labels"
|
@@ -122,7 +134,7 @@ class TestGruffBar < GruffTestCase
|
|
122
134
|
|
123
135
|
def test_fireball
|
124
136
|
g = Gruff::Bar.new
|
125
|
-
g.
|
137
|
+
g.title = "Daring Fireball-type Accumulation Graph"
|
126
138
|
g.hide_line_numbers = true
|
127
139
|
|
128
140
|
running_totals = []
|
data/test/test_mini_side_bar.rb
CHANGED
@@ -1,11 +1,37 @@
|
|
1
1
|
|
2
2
|
require File.dirname(__FILE__) + "/gruff_test_case"
|
3
3
|
|
4
|
-
class
|
4
|
+
class TestMiniSideBar < GruffTestCase
|
5
5
|
|
6
|
-
def
|
6
|
+
def test_one_color
|
7
|
+
# Use a single data set
|
8
|
+
@datasets = [
|
9
|
+
[:Jimmy, [25, 36, 86, 39]]
|
10
|
+
]
|
11
|
+
@labels = {
|
12
|
+
0 => 'Auto',
|
13
|
+
1 => 'Entertainment',
|
14
|
+
2 => 'Food',
|
15
|
+
3 => 'Bus'
|
16
|
+
}
|
17
|
+
|
7
18
|
g = setup_basic_graph(Gruff::Mini::SideBar, 200)
|
8
19
|
write_test_file g, 'mini_side_bar.png'
|
9
20
|
end
|
10
21
|
|
22
|
+
def test_multi_color
|
23
|
+
# @datasets = [
|
24
|
+
# [:Jimmy, [25, 36, 86, 39]]
|
25
|
+
# ]
|
26
|
+
# @labels = {
|
27
|
+
# 0 => 'Auto',
|
28
|
+
# 1 => 'Entertainment',
|
29
|
+
# 2 => 'Food',
|
30
|
+
# 3 => 'Bus'
|
31
|
+
# }
|
32
|
+
|
33
|
+
g = setup_basic_graph(Gruff::Mini::SideBar, 200)
|
34
|
+
write_test_file g, 'mini_side_bar_multi_color.png'
|
35
|
+
end
|
36
|
+
|
11
37
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: gruff
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.
|
7
|
-
date: 2006-
|
6
|
+
version: 0.2.7
|
7
|
+
date: 2006-11-03 00:00:00 -08:00
|
8
8
|
summary: Beautiful graphs for one or multiple datasets.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -31,10 +31,33 @@ authors:
|
|
31
31
|
- Geoffrey Grosenbach
|
32
32
|
files:
|
33
33
|
- CHANGELOG
|
34
|
-
-
|
34
|
+
- Manifest.txt
|
35
35
|
- MIT-LICENSE
|
36
36
|
- Rakefile
|
37
|
-
-
|
37
|
+
- README.txt
|
38
|
+
- assets/pc306715.jpg
|
39
|
+
- assets/city_scene/background/0000.png
|
40
|
+
- assets/city_scene/background/0600.png
|
41
|
+
- assets/city_scene/background/2000.png
|
42
|
+
- assets/city_scene/clouds/cloudy.png
|
43
|
+
- assets/city_scene/clouds/partly_cloudy.png
|
44
|
+
- assets/city_scene/clouds/stormy.png
|
45
|
+
- assets/city_scene/grass/default.png
|
46
|
+
- assets/city_scene/haze/true.png
|
47
|
+
- assets/city_scene/number_sample/1.png
|
48
|
+
- assets/city_scene/number_sample/2.png
|
49
|
+
- assets/city_scene/number_sample/default.png
|
50
|
+
- assets/city_scene/sky/0000.png
|
51
|
+
- assets/city_scene/sky/0200.png
|
52
|
+
- assets/city_scene/sky/0400.png
|
53
|
+
- assets/city_scene/sky/0600.png
|
54
|
+
- assets/city_scene/sky/0800.png
|
55
|
+
- assets/city_scene/sky/1000.png
|
56
|
+
- assets/city_scene/sky/1200.png
|
57
|
+
- assets/city_scene/sky/1400.png
|
58
|
+
- assets/city_scene/sky/1500.png
|
59
|
+
- assets/city_scene/sky/1700.png
|
60
|
+
- assets/city_scene/sky/2000.png
|
38
61
|
- lib/gruff.rb
|
39
62
|
- lib/gruff/area.rb
|
40
63
|
- lib/gruff/bar.rb
|
@@ -46,31 +69,32 @@ files:
|
|
46
69
|
- lib/gruff/photo_bar.rb
|
47
70
|
- lib/gruff/pie.rb
|
48
71
|
- lib/gruff/scene.rb
|
72
|
+
- lib/gruff/side_bar.rb
|
49
73
|
- lib/gruff/side_stacked_bar.rb
|
50
74
|
- lib/gruff/spider.rb
|
51
75
|
- lib/gruff/stacked_bar.rb
|
52
|
-
- lib/gruff/side_bar.rb
|
53
76
|
- lib/gruff/mini/bar.rb
|
77
|
+
- lib/gruff/mini/legend.rb
|
54
78
|
- lib/gruff/mini/pie.rb
|
55
79
|
- lib/gruff/mini/side_bar.rb
|
56
|
-
-
|
80
|
+
- test/gruff_test_case.rb
|
81
|
+
- test/output
|
57
82
|
- test/test_area.rb
|
58
83
|
- test/test_bar.rb
|
59
84
|
- test/test_base.rb
|
60
|
-
- test/gruff_test_case.rb
|
61
85
|
- test/test_legend.rb
|
62
86
|
- test/test_line.rb
|
87
|
+
- test/test_mini_bar.rb
|
88
|
+
- test/test_mini_pie.rb
|
89
|
+
- test/test_mini_side_bar.rb
|
63
90
|
- test/test_net.rb
|
64
|
-
- test/output
|
65
91
|
- test/test_photo.rb
|
66
92
|
- test/test_pie.rb
|
67
93
|
- test/test_scene.rb
|
94
|
+
- test/test_side_bar.rb
|
68
95
|
- test/test_sidestacked_bar.rb
|
69
96
|
- test/test_spider.rb
|
70
97
|
- test/test_stacked_bar.rb
|
71
|
-
- test/test_mini_bar.rb
|
72
|
-
- test/test_mini_pie.rb
|
73
|
-
- test/test_mini_side_bar.rb
|
74
98
|
test_files: []
|
75
99
|
|
76
100
|
rdoc_options: []
|