rubyvis 0.1.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.
Files changed (46) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +3 -0
  3. data/Manifest.txt +44 -0
  4. data/README.txt +64 -0
  5. data/Rakefile +16 -0
  6. data/examples/crimea-line.rb +64 -0
  7. data/examples/first.rb +17 -0
  8. data/examples/second.rb +14 -0
  9. data/lib/rubyvis.rb +43 -0
  10. data/lib/rubyvis/color/color.rb +241 -0
  11. data/lib/rubyvis/color/colors.rb +40 -0
  12. data/lib/rubyvis/color/ramp.rb +0 -0
  13. data/lib/rubyvis/format.rb +19 -0
  14. data/lib/rubyvis/format/date.rb +18 -0
  15. data/lib/rubyvis/format/number.rb +31 -0
  16. data/lib/rubyvis/internals.rb +215 -0
  17. data/lib/rubyvis/javascript_behaviour.rb +64 -0
  18. data/lib/rubyvis/label.rb +0 -0
  19. data/lib/rubyvis/mark.rb +528 -0
  20. data/lib/rubyvis/mark/anchor.rb +22 -0
  21. data/lib/rubyvis/mark/area.rb +34 -0
  22. data/lib/rubyvis/mark/bar.rb +23 -0
  23. data/lib/rubyvis/mark/label.rb +17 -0
  24. data/lib/rubyvis/mark/line.rb +14 -0
  25. data/lib/rubyvis/mark/panel.rb +87 -0
  26. data/lib/rubyvis/mark/rule.rb +28 -0
  27. data/lib/rubyvis/scale.rb +34 -0
  28. data/lib/rubyvis/scale/linear.rb +5 -0
  29. data/lib/rubyvis/scale/ordinal.rb +52 -0
  30. data/lib/rubyvis/scale/quantitative.rb +263 -0
  31. data/lib/rubyvis/scene/svg_bar.rb +31 -0
  32. data/lib/rubyvis/scene/svg_label.rb +51 -0
  33. data/lib/rubyvis/scene/svg_panel.rb +117 -0
  34. data/lib/rubyvis/scene/svg_rule.rb +29 -0
  35. data/lib/rubyvis/scene/svg_scene.rb +118 -0
  36. data/lib/rubyvis/sceneelement.rb +44 -0
  37. data/lib/rubyvis/transform.rb +25 -0
  38. data/spec/internal_spec.rb +146 -0
  39. data/spec/javascript_behaviour_spec.rb +64 -0
  40. data/spec/panel_spec.rb +8 -0
  41. data/spec/scale_linear_spec.rb +121 -0
  42. data/spec/scale_spec.rb +8 -0
  43. data/spec/spec.opts +3 -0
  44. data/spec/spec_helper.rb +27 -0
  45. metadata +160 -0
  46. metadata.gz.sig +2 -0
@@ -0,0 +1,40 @@
1
+ module Rubyvis
2
+ def self.Colors
3
+ Rubyvis::Colors
4
+ end
5
+ def self.colors(*args)
6
+ scale=Rubyvis::Scale.ordinal
7
+ scale.range(*args)
8
+ scale
9
+ end
10
+ module Colors
11
+ def pv
12
+ Rubyvis
13
+ end
14
+ def self.category10(*arguments)
15
+ scale = pv.colors(
16
+ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
17
+ "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf")
18
+ scale.domain(*arguments);
19
+ scale
20
+ end
21
+ def self.category19(*arguments)
22
+ scale = pv.colors(
23
+ "#9c9ede", "#7375b5", "#4a5584", "#cedb9c", "#b5cf6b",
24
+ "#8ca252", "#637939", "#e7cb94", "#e7ba52", "#bd9e39",
25
+ "#8c6d31", "#e7969c", "#d6616b", "#ad494a", "#843c39",
26
+ "#de9ed6", "#ce6dbd", "#a55194", "#7b4173")
27
+ scale.domain(*arguments);
28
+ scale
29
+ end
30
+ def self.category20(*arguments)
31
+ scale = pv.colors(
32
+ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c",
33
+ "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5",
34
+ "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f",
35
+ "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5")
36
+ scale.domain(*arguments);
37
+ scale
38
+ end
39
+ end
40
+ end
File without changes
@@ -0,0 +1,19 @@
1
+ module Rubyvis
2
+ def self.Format
3
+ Rubyvis::Format
4
+ end
5
+
6
+ module Format
7
+ def self.re(s)
8
+ s.gsub(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/, "\\$&")
9
+ end
10
+ def self.number
11
+ Format::Number.new
12
+ end
13
+ def self.date(pattern)
14
+ Format::Date.new(pattern)
15
+ end
16
+ end
17
+ end
18
+ require 'rubyvis/format/number'
19
+ require 'rubyvis/format/date'
@@ -0,0 +1,18 @@
1
+ require 'date'
2
+ module Rubyvis
3
+ module Format
4
+ class Date
5
+ attr_reader :pattern
6
+ def initialize(pattern)
7
+ @pattern=pattern
8
+ #@pad=Rubyvis::Format.pad
9
+ end
10
+ def format(d)
11
+ d.strftime(pattern)
12
+ end
13
+ def parse(s)
14
+ ::Date.strptime(s, pattern)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module Rubyvis
2
+ module Format
3
+ class Number
4
+ def initialize
5
+ @maxi = Infinity # default maximum integer digits
6
+ @mins = 0 # mini, including group separators
7
+ @minf = 0 # default minimum fraction digits
8
+ @maxf = 0 # default maximum fraction digits
9
+ @maxk = 1 # 10^maxf
10
+ @padi = "0" # default integer pad
11
+ @padf = "0" # default fraction pad
12
+ @padg = true # whether group separator affects integer padding
13
+ @decimal = "." # default decimal separator
14
+ @group = "," # default group separator
15
+ @np = "\u2212" # default negative prefix
16
+ @ns = "" # default negative suffix
17
+ end
18
+ def fraction_digits(*arguments)
19
+ if (arguments.size>0)
20
+ min=arguments[0]
21
+ max=arguments[1]
22
+ @minf = min.to_f
23
+ @maxf = (arguments.size > 1) ? max.to_f : @minf
24
+ @maxk = 10**@maxf
25
+ return self
26
+ end
27
+ [minf, maxf]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,215 @@
1
+ module Rubyvis
2
+ # :section: /pv-internals.js
3
+ @@id=0
4
+ def self.id
5
+ @@id+=1
6
+ end
7
+ def self.functor(f)
8
+ (f.is_a? Proc) ? f : lambda {f}
9
+ end
10
+ # :section: /data/Arrays.js
11
+
12
+ def self.map(array, f=nil)
13
+ if f
14
+ array.size.times.map {|i|
15
+ o=o_index(i)
16
+ f.js_call(o, array[i])
17
+ }
18
+ else
19
+ array.dup
20
+ end
21
+ end
22
+ def self.repeat(array, n=2)
23
+ array*n
24
+ end
25
+ def self.cross(a,b)
26
+ array = [];
27
+ a.each {|x|
28
+ b.each {|y|
29
+ array.push([x,y])
30
+ }
31
+ }
32
+ array
33
+ end
34
+ def self.blend(arrays)
35
+ # I love Ruby expresivness
36
+ arrays.inject([]) {|ac,v| ac+v}
37
+ end
38
+ def self.transpose(matrix)
39
+ out=[]
40
+ matrix.size.times do |i|
41
+ matrix[i].size.times do |j|
42
+ out[j]||=Array.new
43
+ out[j][i]=matrix[i][j]
44
+ end
45
+ end
46
+ out
47
+ end
48
+ def self.normalize(array,f=nil)
49
+ norm=Rubyvis.map(array,f)
50
+ sum=pv.sum(norm)
51
+ norm.map {|x| x.quo(sum)}
52
+ end
53
+ def self.o_index(i)
54
+ o=OpenStruct.new :index=>i
55
+ end
56
+ def self.permute(array,indexes, f=nil)
57
+ f=Rubyvis.identity if f.nil?
58
+ indexes.map {|i| o=o_index(i); f.js_call(o, array[i])}
59
+ end
60
+ def self.numerate(keys, f=nil)
61
+ f=Rubyvis.identity if f.nil?
62
+ m = {}
63
+ keys.each_with_index {|x,i|
64
+ o=o_index(i)
65
+ m[f.js_call(o,x)]=i
66
+ }
67
+ m
68
+ end
69
+ def self.uniq(array, f=nil )
70
+ self.map(array,f).uniq
71
+ end
72
+ def self.natural_order(a,b)
73
+ a<=>b
74
+ end
75
+ def self.reverse_order(a,b)
76
+ -(a<=>b)
77
+ end
78
+
79
+ def self.search(array, value, f=nil)
80
+ f = Rubyvis.identity if (f.nil?)
81
+ low = 0
82
+ high = array.size - 1;
83
+ while (low <= high)
84
+ mid = (low + high) >> 1
85
+ midValue = f.call(array[mid]);
86
+ if (midValue < value)
87
+ low = mid + 1;
88
+ elsif (midValue > value)
89
+ high = mid - 1;
90
+ else
91
+ return mid;
92
+ end
93
+ end
94
+ return -low - 1;
95
+ end
96
+ def self.search_index(array,value,f=nil)
97
+ i=Rubyvis.search(array,value,f)
98
+ (i < 0 ) ? (-i-1) : i;
99
+ end
100
+
101
+
102
+ # :section: /data/Numbers.js
103
+
104
+ def self.range(*arguments)
105
+ start, stop, step=arguments
106
+ if (arguments.size == 1)
107
+ stop = start;
108
+ start = 0;
109
+ end
110
+ step||= 1
111
+ raise "range must be finite" if ((stop - start) / step.to_f).infinite?
112
+ array = []
113
+ i = 0
114
+ stop = stop- (stop - start) * 1e-10 #// floating point precision!
115
+ j = start + step * i
116
+ if (step < 0)
117
+ while (j > stop)
118
+ array.push(j)
119
+ i+=1
120
+ j = start + step * i
121
+ end
122
+ else
123
+ while (j < stop)
124
+ array.push(j)
125
+ i+=1
126
+ j = start + step * i
127
+ end
128
+ end
129
+ array
130
+ end
131
+ def self.random(*arguments)
132
+ start,stop,step=arguments
133
+ if (arguments.size == 1)
134
+ stop = start;
135
+ start = 0;
136
+ end
137
+ step||= 1;
138
+ return step ? ((rand() * (stop - start).quo(step)).floor * step + start) : (rand() * (stop - start) + start);
139
+ end
140
+
141
+ def self.sum(array,f=nil)
142
+ if f.nil?
143
+ array.inject(0) {|ac,v| ac+v}
144
+ else
145
+ i=0
146
+ array.inject(0) {|ac,v|
147
+ o=o_index(i);i+=1;
148
+ ac+f.js_call(o,v);
149
+ }
150
+ end
151
+ end
152
+ def self.max(array, f=nil)
153
+ return array.size-1 if f==Rubyvis.index
154
+ f ? Rubyvis.map(array, f).max : array.max
155
+ end
156
+ def self.max_index(array,f=nil)
157
+ a2=Rubyvis.map(array,f)
158
+ max=a2.max
159
+ a2.index(max)
160
+ end
161
+
162
+ def self.min(array, f=nil)
163
+ return array.size-1 if f==Rubyvis.index
164
+ f ? Rubyvis.map(array, f).min : array.min
165
+ end
166
+ def self.min_index(array,f=nil)
167
+ a2=Rubyvis.map(array,f)
168
+ min=a2.min
169
+ a2.index(min)
170
+ end
171
+ def self.mean(array, f=nil)
172
+ Rubyvis.sum(array,f).quo(array.size)
173
+ end
174
+ def self.median(array,f=nil)
175
+ return (array.length - 1).quo(2) if (f == pv.index)
176
+ array = Rubyvis.map(array, f).sort{|a,b| Rubyvis.natural_order(a,b)}
177
+ return array[array.size.quo(2).floor] if (array.length % 2>0)
178
+ i = array.size.quo(2);
179
+ return (array[i - 1] + array[i]).quo(2);
180
+ end
181
+ # Sum of square, really
182
+ def self.variance(array,f=nil)
183
+ return 0 if array.size==1 or array.uniq.size==1
184
+ ar=(f.nil?) ? array : Rubyvis.map(array,f)
185
+ mean=Rubyvis.mean(ar)
186
+ ar.inject(0) {|ac,v| ac+(v-mean)**2}
187
+ end
188
+ def self.deviation(array,f=nil)
189
+ Math::sqrt(self.variance(array,f) / (array.size.to_f-1))
190
+ end
191
+ def self.log(x,b)
192
+ Math::log(x).quo(Math::log(b))
193
+ end
194
+ def self.log_symmetric(x,b)
195
+ (x == 0) ? 0 : ((x < 0) ? -Rubyvis.log(-x, b) : Rubyvis.log(x, b));
196
+ end
197
+ def self.log_adjusted(x,b)
198
+ x if x.is_a? Float and !x.finite?
199
+ negative=x<0
200
+ x += (b - x) / b.to_f if (x < b)
201
+ negative ? -Rubyvis.log(x, b) : Rubyvis.log(x, b);
202
+ end
203
+ def self.log_floor(x,b)
204
+ (x>0) ? b**(Rubyvis.log(x,b).floor) : b**(-(-Rubyvis.log(-x,b)).floor)
205
+ end
206
+ def self.log_ceil(x,b)
207
+ (x > 0) ? b ** (Rubyvis.log(x, b)).ceil : -(b ** -(-Rubyvis.log(-x, b)).ceil);
208
+ end
209
+ def self.radians(degrees)
210
+ (Math::PI/180.0)*degrees
211
+ end
212
+ def self.degrees(radians)
213
+ ((180.0) / Math::PI)*radians
214
+ end
215
+ end
@@ -0,0 +1,64 @@
1
+ class TrueClass
2
+ def to_i
3
+ 1
4
+ end
5
+ end
6
+ class FalseClass
7
+ def to_i
8
+ 0
9
+ end
10
+ end
11
+
12
+
13
+ unless Object.public_method_defined? :instance_exec
14
+ class Object
15
+ module InstanceExecHelper; end
16
+ include InstanceExecHelper
17
+ def instance_exec(*args, &block) # :nodoc:
18
+ begin
19
+ old_critical, Thread.critical = Thread.critical, true
20
+ n = 0
21
+ n += 1 while respond_to?(mname="__instance_exec#{n}")
22
+ InstanceExecHelper.module_eval{ define_method(mname, &block) }
23
+ ensure
24
+ Thread.critical = old_critical
25
+ end
26
+ begin
27
+ ret = send(mname, *args)
28
+ ensure
29
+ InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
30
+ end
31
+ ret
32
+ end
33
+ end
34
+
35
+ end
36
+ # Add javascript-like +apply+ and +call+ methods to Proc,
37
+ # called +js_apply+ and +js_call+, respectivly.
38
+
39
+ class Proc
40
+ # Apply on javascript is very flexible. Can accept more or less
41
+ # variables than explicitly defined parameters on lambda, so the method
42
+ # adds or remove elements according to lambda arity
43
+ #
44
+ def js_apply(obj,args)
45
+ arguments=args.dup
46
+ # Modify numbers of args to works with arity
47
+ min_args=self.arity>0 ? self.arity : (-self.arity)-1
48
+ if args.size > min_args and self.arity>0
49
+ arguments=arguments[0,self.arity]
50
+ elsif args.size < min_args
51
+ arguments+=[nil]*(min_args-args.size)
52
+ end
53
+ #puts "#{args}->#{arguments} (#{self.arity})"
54
+ if self.arity==0
55
+ obj.instance_eval(&self)
56
+ else
57
+ obj.instance_exec(*arguments,&self)
58
+ end
59
+ end
60
+ # Same as js_apply, but using explicit arguments
61
+ def js_call(obj,*args)
62
+ js_apply(obj,args)
63
+ end
64
+ end
File without changes
@@ -0,0 +1,528 @@
1
+ module Rubyvis
2
+ # Represents a data-driven graphical mark. The <tt>Mark</tt> class is
3
+ # the base class for all graphical marks in Protovis; it does not provide any
4
+ # specific rendering functionality, but together with {@link Panel} establishes
5
+ # the core framework.
6
+ class Mark
7
+ @properties={}
8
+
9
+ def self.property_method(name,_def)
10
+ define_method(name) do |*arguments|
11
+ v,dummy = arguments
12
+ if _def and self.scene
13
+ if arguments.size>0
14
+ defs[name]=OpenStruct.new({:id=>(v.nil?) ? 0 : Rubyvis.id, :value=> v})
15
+ return self
16
+ end
17
+ return defs[name]
18
+ end
19
+ if arguments.size>0
20
+ type=(!_def).to_i<<1 | (v.is_a? Proc).to_i
21
+ property_value(name,(type & 1 !=0) ? lambda {|*args| v.js_apply(self, args)} : v)._type=type
22
+ @_properties_types[name]=type
23
+ return self
24
+ end
25
+ i=instance()
26
+ if i.nil?
27
+ raise "No instancia para #{name}"
28
+ else
29
+ #puts "Instancia para #{name}"
30
+
31
+ i.send(name)
32
+ end
33
+ end
34
+ end
35
+ def property_value(name,v)
36
+ prop=OpenStruct.new({:name=>name, :id=>Rubyvis.id, :value=>v})
37
+ @_properties.delete_if{|v| v.name==name}
38
+ @_properties.push(prop)
39
+ @_properties_values[name]=v
40
+ return prop
41
+ end
42
+ def margin(n)
43
+ self.left(n).right(n).top(n).bottom(n)
44
+ end
45
+ def instance(default_index=nil)
46
+ scene=self.scene
47
+ scene||=self.parent.instance(-1).children[self.child_index]
48
+ if(default_index)
49
+ index=self.respond_to?(:index) ? self.index : default_index
50
+ else
51
+ index=scene.size-1
52
+ end
53
+ #puts "index:#{index} , scene.size:#{scene.size}, default_index:#{default_index}"
54
+ scene[index]
55
+ end
56
+
57
+
58
+ def self.attr_accessor_dsl(*attr)
59
+ attr.each do |sym|
60
+ @properties[sym]=true
61
+ sym_w_sm=sym.to_s.gsub(":","")
62
+ self.property_method(sym,false)
63
+ define_method(sym.to_s+"=") {|v|
64
+ self.send(sym,v)
65
+ }
66
+ end
67
+ end
68
+
69
+ attr_accessor :parent, :root, :index, :child_index, :scene, :proto, :target, :scale
70
+ attr_accessor_dsl :data,:visible, :left, :right, :top, :bottom, :title, :reverse, :antialias, :id
71
+
72
+ @scene=nil
73
+ @stack=[]
74
+ @index=nil
75
+ def self.properties
76
+ @properties
77
+ end
78
+ def self.index
79
+ @index
80
+ end
81
+ def self.index=(v)
82
+ @index=v
83
+ end
84
+
85
+
86
+
87
+ def self.scene
88
+ @scene
89
+ end
90
+ def self.scene=(v)
91
+ @scene=v
92
+ end
93
+ def properties
94
+ (self.class).properties
95
+ end
96
+ def Mark.stack
97
+ @stack
98
+ end
99
+ def Mark.stack=(v)
100
+ @stack=v
101
+ end
102
+
103
+ def initialize(opts=Hash.new)
104
+ @_properties_values={}
105
+ @_properties_types={}
106
+ @_properties=[]
107
+ @options=defaults.merge opts
108
+ # @stack=[]
109
+ @options.each {|k,v|
110
+ self.send("#{k}=",v) if self.respond_to? k
111
+ }
112
+ @defs={}
113
+ @child_index=-1
114
+ @index=-1
115
+ @scale=1
116
+ @scene=nil
117
+
118
+ end
119
+ def type
120
+ "mark"
121
+ end
122
+ def _properties
123
+ out={}
124
+ @_properties_values.each {|k,v|
125
+ out[k]=OpenStruct.new({:name=>k.to_s,:value=>v, :_type=>@_properties_types[k]})
126
+ }
127
+ out
128
+ end
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+ def defaults
137
+ {:data=>lambda {|d| [d]}, :visible=>true, :antialias=>true}
138
+ end
139
+ def extend(proto)
140
+ @proto=proto
141
+ @target=target
142
+ self
143
+ end
144
+
145
+ def add(type)
146
+ parent.add(type).extend(self)
147
+ end
148
+ def anchor(name=nil)
149
+ name = "center" if (!name) # default anchor name
150
+ return Rubyvis::Anchor.new(self).name(name).data(lambda {
151
+ self.scene.target.map {|s| s.data} }).visible(lambda {
152
+ self.scene.target[self.index].visible
153
+ }).id(lambda {self.scene.target[self.index].id}).left(lambda {
154
+ s = self.scene.target[self.index]
155
+ w = s.width
156
+ w||=0
157
+ if ['bottom','top','center'].include?(self.name)
158
+ s.left + w / 2.0
159
+ elsif self.name=='left'
160
+ nil
161
+ else
162
+ s.left + w
163
+ end
164
+ }).top(lambda {
165
+ s = self.scene.target[self.index]
166
+ h = s.height
167
+ h||= 0
168
+ if ['left','right','center'].include? self.name
169
+ s.top+h/2.0
170
+ elsif self.name=='top'
171
+ nil
172
+ else
173
+ s.top + h
174
+ end
175
+ }).right(lambda {
176
+ s = self.scene.target[self.index]
177
+ self.name() == "left" ? s.right + (s.width ? s.width : 0) : nil;
178
+ }).bottom(lambda {
179
+ s = self.scene.target[self.index];
180
+ self.name() == "top" ? s.bottom + (s.height ? s.height : 0) : nil;
181
+ }).text_align(lambda {
182
+ if ['bottom','top','center'].include? self.name
183
+ 'center'
184
+ elsif self.name=='right'
185
+ 'right'
186
+ else
187
+ 'left'
188
+ end
189
+ }).text_baseline(lambda {
190
+ if ['right','left','center'].include? self.name
191
+ 'middle'
192
+ elsif self.name=='top'
193
+ 'top'
194
+ else
195
+ 'bottom'
196
+ end
197
+ })
198
+
199
+
200
+
201
+ end
202
+
203
+
204
+
205
+
206
+
207
+ def build_implied(s)
208
+ l=s.left
209
+ r=s.right
210
+ t=s.top
211
+ b=s.bottom
212
+ prop=self.properties
213
+ w = (prop[:width] and !prop[:width].nil?) ? s.width : 0
214
+ h = (prop[:height] and !prop[:height].nil?) ? s.height : 0
215
+ #puts "#{l},#{r},#{t},#{b}"
216
+ #puts "#{w},#{h}"
217
+
218
+ width=self.parent ? self.parent.width(): (w+(l.nil? ? 0 : l)+(r.nil? ? 0 :r))
219
+ if w.nil?
220
+ r||=0
221
+ l||=0
222
+ w=width-r-l
223
+ elsif r.nil?
224
+ if l.nil?
225
+
226
+ r=(width-w) / (2.0)
227
+ l=r
228
+ else
229
+ r=width-w-l
230
+ end
231
+ elsif l.nil?
232
+ l=width-w-r
233
+ end
234
+
235
+ height=self.parent ? self.parent.height(): (h+(t.nil? ? 0 : t )+(b.nil? ? 0 : b))
236
+
237
+ if h.nil?
238
+ t||=0
239
+ b||=0
240
+ h=height-t-b
241
+ elsif b.nil?
242
+ if t.nil?
243
+ t=(height-h) / 2.0
244
+ b=t
245
+ else
246
+ b=height-h-t
247
+ end
248
+ elsif t.nil?
249
+ t=height-h-b
250
+ end
251
+
252
+
253
+
254
+ s.left=l
255
+ s.right=r
256
+ s.top=t
257
+ s.bottom=b
258
+
259
+ # puts "#{l},#{r},#{t},#{b}"
260
+
261
+ s.width=w if prop[:width]
262
+ s.height=h if prop[:height]
263
+ s.text_style=Rubyvis::Color.transparent if prop[:text_style] and !s.text_style
264
+ s.fill_style=Rubyvis::Color.transparent if prop[:fill_style] and !s.fill_style
265
+ s.stroke_style=Rubyvis::Color.transparent if prop[:stroke_style] and !s.stroke_style
266
+ end
267
+
268
+
269
+
270
+
271
+ def pr_svg(name)
272
+ res=self.send(name)
273
+ if res.nil?
274
+ "none"
275
+ else
276
+ res.to_s
277
+ end
278
+ end
279
+ def render_render(mark,depth,scale)
280
+ mark.scale=scale
281
+ if (depth < @indexes.size)
282
+ @stack.unshift(nil)
283
+ if (mark.respond_to? :index)
284
+ render_instance(mark, depth, scale);
285
+ else
286
+ mark.scene.size.times {|i|
287
+ mark.index = i;
288
+ render_instance(mark, depth, scale);
289
+ }
290
+ mark.index=nil
291
+ end
292
+ stack.shift();
293
+ else
294
+ mark.build();
295
+ pv.Scene.scale = scale;
296
+ pv.Scene.update_all(mark.scene);
297
+ end
298
+ mark.scale=nil
299
+ end
300
+ def render_instance(mark,depth,scale)
301
+ s=mark.scene[mark.index]
302
+ if s.visible
303
+ child_index=@indexes[depth]
304
+ child=mark.children[child_index]
305
+ child_index.times {|i|
306
+ mark.children[i].scene=s.children[i]
307
+ }
308
+ Mark.stack[0]=s.data
309
+
310
+ if (child.scene)
311
+ render_render(child,depth+1,scale*s.transform.k)
312
+ else
313
+ child.scene=s.children[child_index]
314
+ render_render(child, depth+1,scale*s.transform.k)
315
+ child.scene=nil
316
+ end
317
+ child_index.times {|i|
318
+ mark.children[i].scene=nil
319
+ }
320
+
321
+ end
322
+ end
323
+ private :render_render, :render_instance
324
+ def bind_bind(mark)
325
+ begin
326
+ @_properties.each {|v|
327
+ k=v.name.to_s
328
+ if !@seen.has_key?(k)
329
+ @seen[k]=v
330
+ case k
331
+ when "data"
332
+ @_data=v
333
+ when "visible"
334
+ @_required.push(v)
335
+ when "id"
336
+ @_required.push(v)
337
+ else
338
+ @types[v._type].push(v)
339
+ end
340
+ end
341
+ }
342
+ end while(mark = mark.proto)
343
+ end
344
+ attr_accessor :binds
345
+ def bind()
346
+ @seen={}
347
+ @types={1=>[],2=>[],3=>[]}
348
+ @_data=nil
349
+ @_required=[]
350
+ bind_bind(self)
351
+ @types[1].reverse!
352
+ @types[3].reverse!
353
+ mark=self
354
+ begin
355
+ properties.each {|name,v|
356
+ if !@seen[name.to_s]
357
+ @seen[name.to_s]=OpenStruct.new(:name=>name.to_s, :_type=>2, :value=>nil)
358
+ @types[2].push(@seen[name.to_s])
359
+ end
360
+ }
361
+ end while(mark=mark.proto)
362
+ @binds=OpenStruct.new({:properties=>@seen, :data=>@_data, :required=>@_required, :optional=>@types[1]+@types[2]+@types[3]
363
+ })
364
+ end
365
+ def render
366
+ parent=self.parent
367
+ @stack=Mark.stack
368
+ if parent and !self.root.scene
369
+ root.render()
370
+ return
371
+ end
372
+ @indexes=[]
373
+ mark=self
374
+ until mark.parent.nil?
375
+ indexes.unshift(mark.child_index)
376
+ end
377
+ self.bind()
378
+ while(parent and !parent.respond_to? :index) do
379
+ parent=parent.parent
380
+ end
381
+ self.context( parent ? parent.scene : nil, parent ? parent.index : -1, lambda {render_render(self.root, 0,1)})
382
+
383
+ end
384
+
385
+ def context_apply(scene,index)
386
+ Mark.scene=scene
387
+ Mark.index=index
388
+ return if(!scene)
389
+ that=scene.mark
390
+ mark=that
391
+ ancestors=[]
392
+ begin
393
+ ancestors.push(mark)
394
+ Mark.stack.push(scene[index].data)
395
+ mark.index=index
396
+ mark.scene=scene
397
+ index=scene.parent_index
398
+ scene=scene.parent
399
+ end while(mark=mark.parent)
400
+ k=1
401
+ ancestors.size.times {|ic|
402
+ i=ancestors.size-ic-1
403
+ mark=ancestors[i]
404
+ mark.scale=k
405
+ k=k*mark.scene[mark.index].transform.k
406
+ }
407
+ if (that.children)
408
+ n=than.children.size
409
+ n.times {|i|
410
+ mark=that.children[i]
411
+ mark.scene=that.scene[that.index].children[i]
412
+ mark.scale=k
413
+ }
414
+
415
+ end
416
+
417
+ end
418
+ def context_clear(scene,index)
419
+ return if !scene
420
+ that=scene.mark
421
+ mark=nil
422
+ if(that.children)
423
+ that.children.size.times {|i|
424
+ mark=that.children[i]
425
+ mark.scene=nil
426
+ mark.scale=nil
427
+ }
428
+
429
+ end
430
+ mark=that
431
+ begin
432
+ Mark.stack.pop
433
+ if(mark.parent)
434
+ mark.scene=nil
435
+ mark.scale=nil
436
+ end
437
+ mark.index=nil
438
+ end while(mark=mark.parent)
439
+ end
440
+ def context(scene,index,f)
441
+ proto=Mark
442
+ stack=Mark.stack
443
+ oscene=Mark.scene
444
+ oindex=Mark.index
445
+ context_clear(oscene,oindex)
446
+ context_apply(scene,index)
447
+ begin
448
+ f.js_apply(self, stack)
449
+ ensure
450
+ context_clear(scene,index)
451
+ context_apply(oscene,oindex)
452
+ end
453
+ end
454
+
455
+ def build
456
+ scene=self.scene
457
+ stack=Mark.stack
458
+ #p self.type
459
+ if(!scene)
460
+ self.scene=SceneElement.new
461
+ scene=self.scene
462
+ scene.mark=self
463
+ scene.type=self.type
464
+ scene.child_index=self.child_index
465
+ if(self.parent)
466
+ scene.parent=self.parent.scene
467
+ scene.parent_index=self.parent.index
468
+ end
469
+ end
470
+ if(self.target)
471
+ scene.target=self.target.instances(scene)
472
+ end
473
+
474
+ data=self.binds.data
475
+ #puts "stack:#{stack}"
476
+ #puts "data_value:#{data.value}"
477
+
478
+ data=(data._type & 1)>0 ? data.value.js_apply(self, stack) : data.value
479
+ #puts "data:#{data}"
480
+
481
+ stack.unshift(nil)
482
+ scene.size=data.size
483
+ data.each_with_index {|d,i|
484
+ Mark.index=self.index=i
485
+ s=scene[i]
486
+ if !s
487
+ scene[i]=s=SceneElement.new
488
+ end
489
+ stack[0]=data[i]
490
+ s.data=data[i]
491
+ build_instance(s)
492
+ }
493
+ Mark.index=-1
494
+ self.index=nil
495
+ stack.shift()
496
+ return self
497
+ end
498
+ def build_instance(s1)
499
+ build_properties(s1, self.binds.required)
500
+ if s1.visible
501
+ build_properties(s1,self.binds.optional)
502
+ build_implied(s1)
503
+ end
504
+ end
505
+ def build_properties(ss, props)
506
+ #p props
507
+ props.each do |prop|
508
+ v=prop.value
509
+
510
+ # p "#{prop.name}=#{v}"
511
+
512
+ if prop._type==3
513
+ v=v.js_apply(self, Mark.stack)
514
+ end
515
+ ss.send((prop.name.to_s+"=").to_sym, v)
516
+ end
517
+ #p ss
518
+ end
519
+ end
520
+ end
521
+
522
+ require 'rubyvis/mark/bar'
523
+ require 'rubyvis/mark/panel'
524
+ require 'rubyvis/mark/rule'
525
+ require 'rubyvis/mark/area'
526
+ require 'rubyvis/mark/anchor'
527
+ require 'rubyvis/mark/label'
528
+