rubyvis 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.5.0 / 2011-02-04
2
+ * Nokogiri used as XML builder. Fall back to REXML if nokogiri is not available or $rubyvis_no_nokogiri=true
3
+
4
+
1
5
  === 0.4.1 / 2011-01-26
2
6
  * All tests run on ruby 1.8.7. Not all pass, because on ruby<1.9 hash order are not preserved
3
7
  * Removed warnings for Ruby 1.9+
data/README.txt CHANGED
@@ -41,6 +41,8 @@ I try to maintain, when posible, complete compatibility with Javascript API, inc
41
41
 
42
42
  User could use +pv+ freely, cause is defined as a global method which call Rubyvis.
43
43
 
44
+ Nokogiri is used as XML library. If not available, or $rubyvis_no_nokogiri is set to true, REXML is used. Nokogiri is 30%-35% faster that REXML on our test.
45
+
44
46
  == CURRENT PROGRESS
45
47
 
46
48
  * pv.js
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'hoe'
7
7
  require 'rubyvis'
8
8
  require 'rspec'
9
9
  require 'rspec/core/rake_task'
10
-
10
+ require 'rubyforge'
11
11
 
12
12
  Hoe.plugin :git
13
13
 
@@ -77,11 +77,17 @@ module Rubyvis
77
77
  end
78
78
 
79
79
  def to_svg
80
- @_canvas.sort.map {|v|
81
- bar = REXML::Formatters::Default.new
82
- out = String.new
83
- bar.write(v[1].elements[1], out)
84
- }.join
80
+ if Rubyvis.xml_engine==:nokogiri
81
+ @_canvas.sort.map {|v|
82
+ v[1].get_element(1).to_xml(:indent => 5, :encoding => 'UTF-8')
83
+ }.join
84
+ else
85
+ @_canvas.sort.map {|v|
86
+ bar = REXML::Formatters::Default.new
87
+ out = String.new
88
+ bar.write(v[1].elements[1], out)
89
+ }.join
90
+ end
85
91
  end
86
92
  def build_implied(s)
87
93
  panel_build_implied(s)
@@ -107,8 +113,15 @@ module Rubyvis
107
113
  @_canvas||={}
108
114
  cache=@_canvas
109
115
  if(!(c=cache[self.index]))
116
+
117
+ if Rubyvis.xml_engine==:nokogiri
118
+ document=Nokogiri::XML::Document.new
119
+ document.root=document.create_element('document')
120
+ Rubyvis.nokogiri_document(document)
121
+ else
110
122
  document=REXML::Document.new
111
- document.add_element("document")
123
+ document.add_element("document")
124
+ end
112
125
  cache[self.index]=document.root
113
126
  c=cache[self.index]
114
127
 
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.area(scenes)
4
- e = scenes._g.elements[1]
4
+ #e = scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  return e if scenes.size==0
6
7
  s=scenes[0]
7
8
  # segmented
@@ -127,7 +128,8 @@ module Rubyvis
127
128
  end
128
129
 
129
130
  def self.area_segment(scenes)
130
- e = scenes._g.elements[1]
131
+ e=scenes._g.get_element(1)
132
+ #e = scenes._g.elements[1]
131
133
  s = scenes[0]
132
134
  pathsT=nil
133
135
  pathsB=nil
@@ -1,13 +1,14 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.bar(scenes)
4
- e=scenes._g.elements[1]
4
+ #e=scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  scenes.each_with_index do |s,i|
6
7
  next unless s.visible
7
8
  fill=s.fill_style
8
9
  stroke=s.stroke_style
9
10
  next if(fill.opacity==0 and stroke.opacity==0)
10
- e=SvgScene.expect(e,'rect', {
11
+ e=SvgScene.expect(e, 'rect', {
11
12
  "shape-rendering"=> s.antialias ? nil : "crispEdges",
12
13
  "pointer-events"=> s.events,
13
14
  "cursor"=> s.cursor,
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.dot(scenes)
4
- e = scenes._g.elements[1]
4
+ #e = scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  scenes.each_with_index {|s,i|
6
7
  s = scenes[i];
7
8
 
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.image(scenes)
4
- e=scenes._g.elements[1]
4
+ #e=scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  scenes.each_with_index do |s,i|
6
7
  next unless s.visible
7
8
  e=self.fill(e,scenes,i)
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.label(scenes)
4
- e=scenes._g.elements[1]
4
+ #e=scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  scenes.each_with_index do |s,i|
6
7
  next unless s.visible
7
8
  fill=s.text_style
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.line(scenes)
4
- e=scenes._g.elements[1]
4
+ #e=scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  return e if (scenes.size < 2)
6
7
  s = scenes[0]
7
8
  # segmented */
@@ -50,8 +51,8 @@ module Rubyvis
50
51
 
51
52
  def self.line_segment(scenes)
52
53
 
53
- e=scenes._g.elements[1]
54
-
54
+ #e=scenes._g.elements[1]
55
+ e=scenes._g.get_element(1)
55
56
  s = scenes[0];
56
57
  paths=nil
57
58
  case s.interpolate
@@ -3,44 +3,70 @@ module Rubyvis
3
3
  def self.panel(scenes)
4
4
  puts " -> panel: #{scenes.inspect}" if $DEBUG
5
5
  g=scenes._g
6
- e=(g.nil?) ? nil : g.elements[1]
6
+ #e=(g.nil?) ? nil : g.elements[1]
7
+ e=(g.nil?) ? nil : g.get_element(1)
7
8
  if g
8
- e=g.elements[1]
9
+ #e=g.elements[1]
10
+ e=g.get_element(1)
9
11
  end
10
12
  scenes.each_with_index do |s,i|
11
13
  next unless s.visible
12
14
 
13
15
  if(!scenes.parent)
14
16
  if g and g.parent!=s.canvas
15
- g=s.canvas.elements[1]
16
- e=(@g.nil?) ? nil : @g.elements[1]
17
+ #g=s.canvas.elements[1]
18
+ g=s.canvas.get_element(1)
19
+ #e=(@g.nil?) ? nil : @g.elements[1]
20
+ e=(@g.nil?) ? nil : @g.get_element(1)
17
21
  end
18
22
  if(!g)
19
23
  g=s.canvas.add_element(self.create('svg'))
20
- g.attributes["font-size"]="10px"
21
- g.attributes["font-family"]="sans-serif"
22
- g.attributes["fill"]="none"
23
- g.attributes["stroke"]="none"
24
- g.attributes["stroke-width"]=1.5
25
- e=g.elements[1]
24
+ g.set_attributes(
25
+ {
26
+ 'font-size'=>"10px",
27
+ 'font-family'=>'sans-serif',
28
+ 'fill'=>'none',
29
+ 'stroke'=>'none',
30
+ 'stroke-width'=>1.5
31
+ }
32
+ )
33
+ e=g.get_element(1)
34
+ # g.attributes["font-size"]="10px"
35
+ # g.attributes["font-family"]="sans-serif"
36
+ # g.attributes["fill"]="none"
37
+ # g.attributes["stroke"]="none"
38
+ # g.attributes["stroke-width"]=1.5
39
+ # e=g.elements[1]
26
40
  end
27
41
  scenes._g=g
28
42
  #p s
29
- g.attributes['width']=s.width+s.left+s.right
30
- g.attributes['height']=s.height+s.top+s.bottom
43
+ g.set_attributes({
44
+ 'width'=>s.width+s.left+s.right,
45
+ 'height'=>s.height+s.top+s.bottom
46
+ })
47
+ #g.attributes['width']=s.width+s.left+s.right
48
+ #g.attributes['height']=s.height+s.top+s.bottom
31
49
  end
32
50
  if s.overflow=='hidden'
33
51
  id=Rubyvis.id.to_s(36)
34
52
  c=self.expect(e,'g',{'clip-path'=>'url(#'+id+')'});
35
53
  g.add_element(c) if(!c.parent)
36
54
  scenes._g=g=c
37
- e=c.elements[1]
55
+ #e=c.elements[1]
56
+ e=c.get_element(1)
38
57
  e=self.expect(e,'clipPath',{'id'=>id})
39
- r=(e.elements[1]) ? e.elements[1] : e.add_element(self.create('rect'))
40
- r.attributes['x']=s.left
41
- r.attributes['y']=s.top
42
- r.attributes['width']=s.width
43
- r.attributes['height']=s.height
58
+ #r=(e.elements[1]) ? e.elements[1] : e.add_element(self.create('rect'))
59
+ r=(e.get_element(1)) ? e.get_element(1) : e.add_element(self.create('rect'))
60
+ r.set_attributes({
61
+ 'x'=>s.left,
62
+ 'y'=>s.top,
63
+ 'width'=>s.width,
64
+ 'height'=>s.height
65
+ })
66
+ #r.attributes['x']=s.left
67
+ #r.attributes['y']=s.top
68
+ #r.attributes['width']=s.width
69
+ #r.attributes['height']=s.height
44
70
  g.add_element(e) if !e.parent
45
71
  e=e.next_sibling_node
46
72
 
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.rule(scenes)
4
- e=scenes._g.elements[1]
4
+ #e=scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  scenes.each_with_index do |s,i|
6
7
  next unless s.visible
7
8
  stroke=s.stroke_style
@@ -11,6 +11,51 @@ require 'rubyvis/scene/svg_curve'
11
11
 
12
12
  class REXML::Element #:nodoc:
13
13
  attr_accessor :_scene
14
+ # 1 number based
15
+ def get_element(i)
16
+ elements[i]
17
+ end
18
+ def set_attributes(h)
19
+ h.each do |k,v|
20
+ attributes[k]=v
21
+ end
22
+ end
23
+ #private :attributes
24
+ #private :elements
25
+ end
26
+
27
+ module Nokogiri
28
+ module XML
29
+ class Node
30
+ attr_accessor :_scene
31
+ def add_element(c)
32
+ add_child(c)
33
+ end
34
+
35
+ def set_attributes(h)
36
+ h.each do |k,v|
37
+ set_attribute(k,v.to_s)
38
+ end
39
+ end
40
+ def get_element(i)
41
+ elements[i-1]
42
+ end
43
+ #private :elements
44
+ #private :attributes
45
+ def next_sibling_node
46
+ next_sibling
47
+ end
48
+ def delete_attribute(name)
49
+ remove_attribute(name)
50
+ end
51
+ def text
52
+ content
53
+ end
54
+ def text=(v)
55
+ self.content=v
56
+ end
57
+ end
58
+ end
14
59
  end
15
60
 
16
61
  module Rubyvis
@@ -67,11 +112,19 @@ module Rubyvis
67
112
  end
68
113
  end
69
114
  def self.create(type)
70
- el=REXML::Element.new "#{type}"
71
- if type=='svg'
72
- el.add_namespace(self.svg)
73
- #el.add_namespace("xmlns:xmlns", self.xmlns)
74
- el.add_namespace("xmlns:xlink", self.xlink)
115
+ if Rubyvis.xml_engine==:nokogiri
116
+ el=Rubyvis.nokogiri_document.create_element("#{type}")
117
+ if type=='svg'
118
+ el.add_namespace(nil, self.svg)
119
+ el.add_namespace('xlink', self.xlink)
120
+ end
121
+ else
122
+ el=REXML::Element.new "#{type}"
123
+ if type=='svg'
124
+ el.add_namespace(self.svg)
125
+ #el.add_namespace("xmlns:xmlns", self.xmlns)
126
+ el.add_namespace("xmlns:xlink", self.xlink)
127
+ end
75
128
  end
76
129
  el
77
130
  end
@@ -104,7 +157,9 @@ module Rubyvis
104
157
  e.parent.replace_child(a, e) if (e.parent)
105
158
  a.add_element(e)
106
159
  end
107
- a.add_attribute('xlink:title',s.title)
160
+ #a.add_attribute('xlink:title',s.title)
161
+ a.set_attributes('xlink:title' => s.title)
162
+
108
163
  return a;
109
164
  end
110
165
  a.parent_node.replace_child(e, a) if (a)
@@ -114,7 +169,8 @@ module Rubyvis
114
169
  def self.expect(e, type, attributes, style=nil)
115
170
 
116
171
  if (e)
117
- e = e.elements[1] if (e.name == "a")
172
+ #e = e.elements[1] if (e.name == "a")
173
+ e=e.get_element(1) if (e.name == 'a')
118
174
  if (e.name != type)
119
175
  n = self.create(type);
120
176
  e.parent.replace_child(e, n);
@@ -128,7 +184,8 @@ module Rubyvis
128
184
  if (value.nil?)
129
185
  e.delete_attribute(name)
130
186
  else
131
- e.attributes[name]=value
187
+ e.set_attributes(name=>value)
188
+ #e.attributes[name]=value
132
189
  end
133
190
  }
134
191
 
@@ -145,12 +202,12 @@ module Rubyvis
145
202
  if (value.nil?)
146
203
  array_styles.delete(name)
147
204
  else
148
-
149
205
  array_styles[name]=value
150
206
  end
151
207
  }
152
208
  if array_styles.size>0
153
- e.attributes["style"]=array_styles.map {|k,v| "#{k}:#{v}"}.join(";")
209
+ #e.attributes["style"]=array_styles.map {|k,v| "#{k}:#{v}"}.join(";")
210
+ e.set_attributes('style'=> array_styles.map {|k,v| "#{k}:#{v}"}.join(";"))
154
211
  end
155
212
  end
156
213
  e
@@ -1,7 +1,8 @@
1
1
  module Rubyvis
2
2
  module SvgScene
3
3
  def self.wedge(scenes)
4
- e=scenes._g.elements[1]
4
+ #e=scenes._g.elements[1]
5
+ e=scenes._g.get_element(1)
5
6
  scenes.each_with_index do |s,i|
6
7
  next unless s.visible
7
8
  fill=s.fill_style
data/lib/rubyvis.rb CHANGED
@@ -28,11 +28,13 @@ require 'rubyvis/scene/svg_scene'
28
28
  require 'rubyvis/transform'
29
29
  require 'rubyvis/mark/shorcut_methods'
30
30
 
31
-
31
+ # = Rubyvis
32
+ # Ruby port of Protovis
33
+ #
32
34
  module Rubyvis
33
- @document=nil
35
+ @@nokogiri=nil
34
36
  # Rubyvis version
35
- VERSION = '0.4.1'
37
+ VERSION = '0.5.0'
36
38
  # Protovis API on which current Rubyvis is based
37
39
  PROTOVIS_API_VERSION='3.3'
38
40
  # You actually can do it! http://snipplr.com/view/2137/uses-for-infinity-in-ruby/
@@ -50,7 +52,33 @@ module Rubyvis
50
52
  def self.identity
51
53
  lambda {|x,*args| x}
52
54
  end
55
+ def self.has_nokogiri?
56
+ if @@nokogiri.nil?
57
+ begin
58
+ require 'nokogiri'
59
+ @@nokogiri=true
60
+ rescue LoadError
61
+ @@nokogiri=false
62
+ end
63
+ end
64
+ @@nokogiri
65
+ end
66
+ def self.xml_engine
67
+ if has_nokogiri? and !$rubyvis_no_nokogiri
68
+ :nokogiri
69
+ else
70
+ puts "rexml"
71
+ :rexml
72
+ end
73
+ end
74
+
53
75
 
76
+ def self.nokogiri_document(v=nil)
77
+ if !v.nil?
78
+ @@nokogiri_document=v
79
+ end
80
+ @@nokogiri_document
81
+ end
54
82
  # Returns <tt>self.index</tt>. This method is provided for convenience for use
55
83
  # with scales. For example, to color bars by their index, say:
56
84
  #
@@ -1,5 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
2
- describe "Ruby API for Rubyvis" do
2
+ shared_examples_for "Ruby API for Rubyvis" do
3
3
  before do
4
4
  @h=200
5
5
  @w=200
@@ -44,4 +44,27 @@ describe "Ruby API for Rubyvis" do
44
44
  svg1.should==svg2
45
45
 
46
46
  end
47
- end
47
+ end
48
+
49
+ describe "Rubyvis with REXML" do
50
+ before(:all) do
51
+ $rubyvis_no_nokogiri=true
52
+ end
53
+ after(:all) do
54
+ $rubyvis_no_nokogiri=false
55
+ end
56
+ it_should_behave_like "Ruby API for Rubyvis"
57
+ end
58
+
59
+ if Rubyvis.has_nokogiri?
60
+ describe "Rubyvis with Nokogiri" do
61
+
62
+ before(:all) do
63
+ $rubyvis_no_nokogiri=false
64
+ end
65
+
66
+ it_should_behave_like "Ruby API for Rubyvis"
67
+
68
+
69
+ end
70
+ end
data/spec/spec_helper.rb CHANGED
@@ -94,6 +94,7 @@ end
94
94
  RSpec::Matchers.define :have_svg_attributes do |exp|
95
95
  match do |obs|
96
96
  exp.each {|k,v|
97
+ obs.attributes[k].should be_true
97
98
  obs.attributes[k].value.should==v
98
99
  }
99
100
  end
@@ -193,7 +194,7 @@ Rspec::Matchers.define :have_same_svg_elements do |exp|
193
194
  correct
194
195
  end
195
196
  failure_message_for_should do |obs|
196
- "#{@error[:type]}: #{@error[:exp].to_s} expected, but #{@error[:obs]} retrieved, on attr #{@error[:attr]} -> #{@error[:i]} : #{@error[:exp_attr]} <> #{@error[:obs_attr]}"
197
+ "#{@error[:type]}: #{@error[:exp].to_s} expected, but #{@error[:obs]} retrieved, on #{@error[:attr]} -> #{@error[:i]} : '#{@error[:exp_attr]}' <> '#{@error[:obs_attr]}'"
197
198
  end
198
199
 
199
200
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 4
8
- - 1
9
- version: 0.4.1
7
+ - 5
8
+ - 0
9
+ version: 0.5.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Claudio Bustos
@@ -35,7 +35,7 @@ cert_chain:
35
35
  rpP0jjs0
36
36
  -----END CERTIFICATE-----
37
37
 
38
- date: 2011-01-26 00:00:00 -03:00
38
+ date: 2011-02-04 00:00:00 -03:00
39
39
  default_executable:
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
metadata.gz.sig CHANGED
Binary file