rubyvis 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+