svg_graph 0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,161 @@
1
+ #! /usr/bin/env ruby
2
+ ################################################################################
3
+ # #
4
+ # Name: install.rb #
5
+ # Author: Sean E Russell <ser@germane-software.com> #
6
+ # Version: $Id: $
7
+ # Date: *2002-174 #
8
+ # Description: #
9
+ # This is a generic installation script for pure ruby sources. Features #
10
+ # include: #
11
+ # * Clean uninstall #
12
+ # * Installation into an absolute path #
13
+ # * Installation into a temp path (useful for systems like Portage) #
14
+ # * Noop mode, for testing #
15
+ # To set for a different system, change the SRC directory to point to the #
16
+ # package name / source directory for the project. #
17
+ # #
18
+ ################################################################################
19
+
20
+ # CHANGE THIS
21
+ SRC = ['SVG' ]
22
+ STRIP = ''
23
+ SETVERSION = 'SVG'
24
+ SRCVERSION = '0.6.1'
25
+ DATE = '+2005/058'
26
+
27
+ ################################################################################
28
+ # CHANGE NOTHING BELOW THIS LINE
29
+
30
+ Dir.chdir ".." if Dir.pwd =~ /bin.?$/
31
+
32
+ require 'getoptlong'
33
+ require 'rbconfig'
34
+ require 'ftools'
35
+ require 'find'
36
+
37
+ opts = GetoptLong.new( [ '--uninstall', '-u', GetoptLong::NO_ARGUMENT],
38
+ [ '--destdir', '-d', GetoptLong::REQUIRED_ARGUMENT ],
39
+ [ '--target', '-t', GetoptLong::REQUIRED_ARGUMENT ],
40
+ [ '--concurrent', '-c', GetoptLong::NO_ARGUMENT],
41
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT],
42
+ [ '--noop', '-n', GetoptLong::NO_ARGUMENT])
43
+
44
+
45
+ destdir = File.join(Config::CONFIG['sitedir'],
46
+ "#{Config::CONFIG['MAJOR']}.#{Config::CONFIG['MINOR']}")
47
+
48
+ uninstall = false
49
+ prepend = nil
50
+ help = false
51
+ opts.each do |opt,arg|
52
+ case opt
53
+ when '--concurrent'
54
+ CONCURRENT = true
55
+ when '--destdir'
56
+ prepend = arg
57
+ when '--uninstall'
58
+ uninstall = true
59
+ when '--target'
60
+ destdir = arg
61
+ when '--help'
62
+ help = true
63
+ when '--noop'
64
+ NOOP = true
65
+ end
66
+ end
67
+
68
+ destdir = File.join prepend, destdir if prepend
69
+
70
+ def transmogrify( dir )
71
+ dir = dir.sub( /^#{STRIP}\//, '' )
72
+ if defined? CONCURRENT
73
+ dir.sub( /#{SETVERSION}/, "#{SETVERSION}-#{SRCVERSION}")
74
+ else
75
+ dir
76
+ end
77
+ end
78
+
79
+ if help
80
+ puts "Installs #{SRC.inspect}.\nUsage: #$0 [[-u] [-n] [-c] [-t <dir>|-d <dir>]|-h]"
81
+ puts " -u --uninstall\n Uninstalls the package"
82
+ puts " -c --concurrent\n Install concurrently, IE, into"
83
+ for d in SRC
84
+ puts " #{destdir}/#{transmogrify( d )}"
85
+ end
86
+ puts " The default behavior is to upgrade the current installation,"
87
+ puts " by installing into"
88
+ for d in SRC
89
+ puts " #{destdir}/#{transmogrify( d )}"
90
+ end
91
+ puts " -t --target\n Installs the software at an absolute location, EG:"
92
+ puts " #$0 -t /usr/local/lib/ruby"
93
+ puts " will put the software directly underneath /usr/local/lib/ruby;"
94
+ for d in SRC
95
+ puts " /usr/local/lib/ruby/#{transmogrify( d )}"
96
+ end
97
+ puts " -d --destdir\n Installs the software at a relative location, EG:"
98
+ puts " #$0 -d /tmp"
99
+ puts " will put the software under tmp, using your ruby environment."
100
+ for d in SRC
101
+ puts " /tmp#{destdir}/#{transmogrify( d )}"
102
+ end
103
+ puts " -n --noop\n Don't actually do anything; just print out what it"
104
+ puts " would do."
105
+ exit 0
106
+ end
107
+
108
+ def install destdir
109
+ puts "Installing in #{destdir}"
110
+ begin
111
+ for src in SRC
112
+ Find.find(src) { |file|
113
+ dstfile = transmogrify( file )
114
+ next if file =~ /CVS|\.svn/
115
+ dst = File.join( destdir, dstfile )
116
+ if defined? NOOP
117
+ puts ">> #{dst}" if file =~ /\.rb$/
118
+ else
119
+ File.makedirs( File.dirname(dst) )
120
+ File.install(file, dst, 0644, true) if file =~ /\.rb$/
121
+ end
122
+ }
123
+ end
124
+ rescue
125
+ puts $!
126
+ end
127
+ end
128
+
129
+ def uninstall destdir
130
+ puts "Uninstalling in #{destdir}"
131
+ begin
132
+ puts "Deleting:"
133
+ dirs = []
134
+ Find.find(File.join(destdir,SRC)) do |file|
135
+ file.sub!( /#{SRC}/, "#{SRC}-#{SRCVERSION}") if defined? CONCURRENT
136
+ if defined? NOOP
137
+ puts "-- #{file}" if File.file? file
138
+ else
139
+ File.rm_f file,true if File.file? file
140
+ end
141
+ dirs << file if File.directory? file
142
+ end
143
+ dirs.sort { |x,y|
144
+ y.length <=> x.length
145
+ }.each { |d|
146
+ if defined? NOOP
147
+ puts "-- #{d}"
148
+ else
149
+ puts d
150
+ Dir.delete d
151
+ end
152
+ }
153
+ rescue
154
+ end
155
+ end
156
+
157
+ if uninstall
158
+ uninstall destdir
159
+ else
160
+ install destdir
161
+ end
@@ -0,0 +1,11 @@
1
+
2
+ require 'svg_graph/BarHorizontal'
3
+ require 'svg_graph/Graph'
4
+ require 'svg_graph/Line'
5
+ require 'svg_graph/Pie'
6
+ require 'svg_graph/Plot'
7
+ require 'svg_graph/Schedule'
8
+ require 'svg_graph/TimeSeries'
9
+ require 'svg_graph/version'
10
+
11
+ SvgGraph = SVG::Graph
@@ -0,0 +1,148 @@
1
+ require 'rexml/document'
2
+ require 'svg_graph/Graph'
3
+ require 'svg_graph/BarBase'
4
+
5
+ module SVG
6
+ module Graph
7
+ # === Create presentation quality SVG bar graphs easily
8
+ #
9
+ # = Synopsis
10
+ #
11
+ # require 'SVG/Graph/Bar'
12
+ #
13
+ # fields = %w(Jan Feb Mar);
14
+ # data_sales_02 = [12, 45, 21]
15
+ #
16
+ # graph = SVG::Graph::Bar.new(
17
+ # :height => 500,
18
+ # :width => 300,
19
+ # :fields => fields
20
+ # )
21
+ #
22
+ # graph.add_data(
23
+ # :data => data_sales_02,
24
+ # :title => 'Sales 2002'
25
+ # )
26
+ #
27
+ # print "Content-type: image/svg+xml\r\n\r\n"
28
+ # print graph.burn
29
+ #
30
+ # = Description
31
+ #
32
+ # This object aims to allow you to easily create high quality
33
+ # SVG[http://www.w3c.org/tr/svg bar graphs. You can either use the default
34
+ # style sheet or supply your own. Either way there are many options which
35
+ # can be configured to give you control over how the graph is generated -
36
+ # with or without a key, data elements at each point, title, subtitle etc.
37
+ #
38
+ # = Notes
39
+ #
40
+ # The default stylesheet handles upto 12 data sets, if you
41
+ # use more you must create your own stylesheet and add the
42
+ # additional settings for the extra data sets. You will know
43
+ # if you go over 12 data sets as they will have no style and
44
+ # be in black.
45
+ #
46
+ # = Examples
47
+ #
48
+ # * http://germane-software.com/repositories/public/SVG/test/test.rb
49
+ #
50
+ # = See also
51
+ #
52
+ # * SVG::Graph::Graph
53
+ # * SVG::Graph::BarHorizontal
54
+ # * SVG::Graph::Line
55
+ # * SVG::Graph::Pie
56
+ # * SVG::Graph::Plot
57
+ # * SVG::Graph::TimeSeries
58
+ class Bar < BarBase
59
+ include REXML
60
+
61
+ # See Graph::initialize and BarBase::set_defaults
62
+ def set_defaults
63
+ super
64
+ self.top_align = self.top_font = 1
65
+ end
66
+
67
+ protected
68
+
69
+ def get_x_labels
70
+ @config[:fields]
71
+ end
72
+
73
+ def get_y_labels
74
+ maxvalue = max_value
75
+ minvalue = min_value
76
+ range = maxvalue - minvalue
77
+
78
+ top_pad = range == 0 ? 10 : range / 20.0
79
+ scale_range = (maxvalue + top_pad) - minvalue
80
+
81
+ scale_division = scale_divisions || (scale_range / 10.0)
82
+
83
+ if scale_integers
84
+ scale_division = scale_division < 1 ? 1 : scale_division.round
85
+ end
86
+
87
+ rv = []
88
+ maxvalue = maxvalue%scale_division == 0 ?
89
+ maxvalue : maxvalue + scale_division
90
+ minvalue.step( maxvalue, scale_division ) {|v| rv << v}
91
+ return rv
92
+ end
93
+
94
+ def x_label_offset( width )
95
+ width / 2.0
96
+ end
97
+
98
+ def draw_data
99
+ minvalue = min_value
100
+ fieldwidth = field_width
101
+
102
+ unit_size = (@graph_height.to_f - font_size*2*top_font) /
103
+ (get_y_labels.max - get_y_labels.min)
104
+ bargap = bar_gap ? (fieldwidth < 10 ? fieldwidth / 2 : 10) : 0
105
+
106
+ bar_width = fieldwidth - bargap
107
+ bar_width /= @data.length if stack == :side
108
+ x_mod = (@graph_width-bargap)/2 - (stack==:side ? bar_width/2 : 0)
109
+
110
+ bottom = @graph_height
111
+
112
+ field_count = 0
113
+ @config[:fields].each_index { |i|
114
+ dataset_count = 0
115
+ for dataset in @data
116
+
117
+ # cases (assume 0 = +ve):
118
+ # value min length
119
+ # +ve +ve value - min
120
+ # +ve -ve value - 0
121
+ # -ve -ve value.abs - 0
122
+
123
+ value = dataset[:data][i]
124
+
125
+ left = (fieldwidth * field_count)
126
+
127
+ length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
128
+ # top is 0 if value is negative
129
+ top = bottom - (((value < 0 ? 0 : value) - minvalue) * unit_size)
130
+ left += bar_width * dataset_count if stack == :side
131
+
132
+ @graph.add_element( "rect", {
133
+ "x" => left.to_s,
134
+ "y" => top.to_s,
135
+ "width" => bar_width.to_s,
136
+ "height" => length.to_s,
137
+ "class" => "fill#{dataset_count+1}"
138
+ })
139
+
140
+ make_datapoint_text(left + bar_width/2.0, top - 6, value.to_s)
141
+ dataset_count += 1
142
+ end
143
+ field_count += 1
144
+ }
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,139 @@
1
+ require 'rexml/document'
2
+ require 'svg_graph/Graph'
3
+
4
+ module SVG
5
+ module Graph
6
+ # = Synopsis
7
+ #
8
+ # A superclass for bar-style graphs. Do not attempt to instantiate
9
+ # directly; use one of the subclasses instead.
10
+ #
11
+ # = Author
12
+ #
13
+ # Sean E. Russell <serATgermaneHYPHENsoftwareDOTcom>
14
+ #
15
+ # Copyright 2004 Sean E. Russell
16
+ # This software is available under the Ruby license[LICENSE.txt]
17
+ #
18
+ class BarBase < SVG::Graph::Graph
19
+ # Ensures that :fields are provided in the configuration.
20
+ def initialize config
21
+ raise "fields was not supplied or is empty" unless config[:fields] &&
22
+ config[:fields].kind_of?(Array) &&
23
+ config[:fields].length > 0
24
+ super
25
+ end
26
+
27
+ # In addition to the defaults set in Graph::initialize, sets
28
+ # [bar_gap] true
29
+ # [stack] :overlap
30
+ def set_defaults
31
+ init_with( :bar_gap => true, :stack => :overlap )
32
+ end
33
+
34
+ # Whether to have a gap between the bars or not, default
35
+ # is true, set to false if you don't want gaps.
36
+ attr_accessor :bar_gap
37
+ # How to stack data sets. :overlap overlaps bars with
38
+ # transparent colors, :top stacks bars on top of one another,
39
+ # :side stacks the bars side-by-side. Defaults to :overlap.
40
+ attr_accessor :stack
41
+
42
+
43
+ protected
44
+
45
+ def max_value
46
+ @data.collect{|x| x[:data].max}.max
47
+ end
48
+
49
+ def min_value
50
+ min = 0
51
+ if min_scale_value.nil?
52
+ min = @data.collect{|x| x[:data].min}.min
53
+ min = min > 0 ? 0 : min
54
+ else
55
+ min = min_scale_value
56
+ end
57
+ return min
58
+ end
59
+
60
+ def get_css
61
+ return <<EOL
62
+ /* default fill styles for multiple datasets (probably only use a single dataset on this graph though) */
63
+ .key1,.fill1{
64
+ fill: #ff0000;
65
+ fill-opacity: 0.5;
66
+ stroke: none;
67
+ stroke-width: 0.5px;
68
+ }
69
+ .key2,.fill2{
70
+ fill: #0000ff;
71
+ fill-opacity: 0.5;
72
+ stroke: none;
73
+ stroke-width: 1px;
74
+ }
75
+ .key3,.fill3{
76
+ fill: #00ff00;
77
+ fill-opacity: 0.5;
78
+ stroke: none;
79
+ stroke-width: 1px;
80
+ }
81
+ .key4,.fill4{
82
+ fill: #ffcc00;
83
+ fill-opacity: 0.5;
84
+ stroke: none;
85
+ stroke-width: 1px;
86
+ }
87
+ .key5,.fill5{
88
+ fill: #00ccff;
89
+ fill-opacity: 0.5;
90
+ stroke: none;
91
+ stroke-width: 1px;
92
+ }
93
+ .key6,.fill6{
94
+ fill: #ff00ff;
95
+ fill-opacity: 0.5;
96
+ stroke: none;
97
+ stroke-width: 1px;
98
+ }
99
+ .key7,.fill7{
100
+ fill: #00ffff;
101
+ fill-opacity: 0.5;
102
+ stroke: none;
103
+ stroke-width: 1px;
104
+ }
105
+ .key8,.fill8{
106
+ fill: #ffff00;
107
+ fill-opacity: 0.5;
108
+ stroke: none;
109
+ stroke-width: 1px;
110
+ }
111
+ .key9,.fill9{
112
+ fill: #cc6666;
113
+ fill-opacity: 0.5;
114
+ stroke: none;
115
+ stroke-width: 1px;
116
+ }
117
+ .key10,.fill10{
118
+ fill: #663399;
119
+ fill-opacity: 0.5;
120
+ stroke: none;
121
+ stroke-width: 1px;
122
+ }
123
+ .key11,.fill11{
124
+ fill: #339900;
125
+ fill-opacity: 0.5;
126
+ stroke: none;
127
+ stroke-width: 1px;
128
+ }
129
+ .key12,.fill12{
130
+ fill: #9966FF;
131
+ fill-opacity: 0.5;
132
+ stroke: none;
133
+ stroke-width: 1px;
134
+ }
135
+ EOL
136
+ end
137
+ end
138
+ end
139
+ end