require 'rubyvis/scene/svg_panel' require 'rubyvis/scene/svg_bar' require 'rubyvis/scene/svg_rule' require 'rubyvis/scene/svg_label' require 'rubyvis/scene/svg_line' require 'rubyvis/scene/svg_dot' require 'rubyvis/scene/svg_area' require 'rubyvis/scene/svg_wedge' require 'rubyvis/scene/svg_image' require 'rubyvis/scene/svg_curve' class REXML::Element #:nodoc: attr_accessor :_scene end module Rubyvis module SvgScene # :nodoc: #include REXML def self.svg "http://www.w3.org/2000/svg" end; def self.xmlns "http://www.w3.org/2000/xmlns" end def self.xlink "http://www.w3.org/1999/xlink" end def self.xhtml "http://www.w3.org/1999/xhtml" end @scale=1 def self.scale @scale end def self.scale=(v) @scale=v end IMPLICIT={:svg=>{ "shape-rendering"=> "auto", "pointer-events"=> "painted", "x"=> 0, "y"=> 0, "dy"=> 0, "text-anchor"=> "start", "transform"=> "translate(0,0)", #"fill"=> "none", "fill-opacity"=> 1, "stroke"=> "none", "stroke-opacity"=> 1, "stroke-width"=> 1.5, "stroke-linejoin"=> "miter" },:css=>{"font"=>"10px sans-serif"} } def self.update_all(scenes) puts "update_all: #{scenes.inspect}" if $DEBUG if (scenes.size>0 and scenes[0].reverse and scenes.type!='line' and scenes.type!='area') scenes=scenes.reverse end self.remove_siblings(self.send(scenes.type, scenes)) end def self.remove_siblings(e) while(e) n=e.next_sibling_node e.remove e=n end end def self.create(type) el=REXML::Element.new "#{type}" if type=='svg' el.add_namespace(self.svg) #el.add_namespace("xmlns:xmlns", self.xmlns) el.add_namespace("xmlns:xlink", self.xlink) end el end def self.append(e,scenes,index) e._scene=OpenStruct.new({:scenes=>scenes, :index=>index}) e=self.title(e, scenes[index]) if(!e.parent) scenes._g.add_element(e) end e.next_sibling_node end # Applies a title tooltip to the specified element e, using the # title property of the specified scene node s. Note that # this implementation does not create an SVG title element as a child # of e; although this is the recommended standard, it is only # supported in Opera. Instead, an anchor element is created around the element # e, and the xlink:title attribute is set accordingly. # # @param e an SVG element. # @param s a scene node. def self.title(e,s) a = e.parent a=nil if (a and (a.tag_name != "a")) if (s.title) if (!a) a = self.create("a") e.parent.replace_child(a, e) if (e.parent) a.add_element(e) end a.add_attribute('xlink:title',s.title) return a; end a.parent_node.replace_child(e, a) if (a) e end def self.expect(e, type, attributes, style=nil) if (e) e = e.elements[1] if (e.name == "a") if (e.name != type) n = self.create(type); e.parent.replace_child(e, n); e = n end else e = self.create(type) end attributes.each {|name,value| value = nil if (value == IMPLICIT[:svg][name]) if (value.nil?) e.delete_attribute(name) else e.attributes[name]=value end } if(style) base_style=e.attributes['style'] base_style||="" array_styles={} base_style.split(";").each {|v| v=~/\s*(.+)\s*:\s*(.+)/ array_styles[$1]=$2 } style.each {|name,value| value=nil if value==IMPLICIT[:css][name] if (value.nil?) array_styles.delete(name) else array_styles[name]=value end } if array_styles.size>0 e.attributes["style"]=array_styles.map {|k,v| "#{k}:#{v}"}.join(";") end end e end end end