lib/rubyvis/mark.rb in rubyvis-0.1.0 vs lib/rubyvis/mark.rb in rubyvis-0.1.1

- old
+ new

@@ -17,11 +17,11 @@ return defs[name] end if arguments.size>0 type=(!_def).to_i<<1 | (v.is_a? Proc).to_i property_value(name,(type & 1 !=0) ? lambda {|*args| v.js_apply(self, args)} : v)._type=type - @_properties_types[name]=type + #@_properties_types[name]=type return self end i=instance() if i.nil? raise "No instancia para #{name}" @@ -31,14 +31,14 @@ i.send(name) end end end def property_value(name,v) - prop=OpenStruct.new({:name=>name, :id=>Rubyvis.id, :value=>v}) + prop=Property.new({:name=>name, :id=>Rubyvis.id, :value=>v}) @_properties.delete_if{|v| v.name==name} @_properties.push(prop) - @_properties_values[name]=v + #@_properties_values[name]=v return prop end def margin(n) self.left(n).right(n).top(n).bottom(n) end @@ -65,22 +65,23 @@ } end end attr_accessor :parent, :root, :index, :child_index, :scene, :proto, :target, :scale - attr_accessor_dsl :data,:visible, :left, :right, :top, :bottom, :title, :reverse, :antialias, :id + attr_reader :_properties + attr_accessor_dsl :data,:visible, :left, :right, :top, :bottom, :cursor, :title, :reverse, :antialias, :events, :id @scene=nil @stack=[] @index=nil def self.properties @properties end - def self.index + def Mark.index @index end - def self.index=(v) + def Mark.index=(v) @index=v end @@ -99,16 +100,16 @@ def Mark.stack=(v) @stack=v end def initialize(opts=Hash.new) - @_properties_values={} - @_properties_types={} + #@_properties_values={} + #@_properties_types={} @_properties=[] - @options=defaults.merge opts + #@options=opts # @stack=[] - @options.each {|k,v| + opts.each {|k,v| self.send("#{k}=",v) if self.respond_to? k } @defs={} @child_index=-1 @index=-1 @@ -117,39 +118,59 @@ end def type "mark" end - def _properties - out={} - @_properties_values.each {|k,v| - out[k]=OpenStruct.new({:name=>k.to_s,:value=>v, :_type=>@_properties_types[k]}) - } - out + def self.defaults + Mark.new({:data=>lambda {|d| [d]}, :visible=>true, :antialias=>true, :events=>'painted'}) end - - - - - - - - def defaults - {:data=>lambda {|d| [d]}, :visible=>true, :antialias=>true} - end def extend(proto) @proto=proto - @target=target + @target=proto.target self end + def instances(source) + + mark = self + index = [] + scene=nil + while (!(scene = mark.scene)) do + source = source.parent; + index.push(OpenStruct.new({:index=>source.index, :child_index=>mark.child_index})) + mark = mark.parent + end + while (index.size>0) do + i = index.pop() + scene = scene[i.index].children[i.child_index] + end + # + # When the anchor target is also an ancestor, as in the case of adding + # to a panel anchor, only generate one instance per panel. Also, set + # the margins to zero, since they are offset by the enclosing panel. + # / + if (self.respond_to? :index and self.index) + + s = scene[self.index].dup + s.right = s.top = s.left = s.bottom = 0; + return [s]; + end + return scene; +end + + + + + + + def add(type) parent.add(type).extend(self) end - def anchor(name=nil) - name = "center" if (!name) # default anchor name - return Rubyvis::Anchor.new(self).name(name).data(lambda { + def anchor(name="center") + + anchor=Rubyvis::Anchor.new(self).name(name).data(lambda { self.scene.target.map {|s| s.data} }).visible(lambda { self.scene.target[self.index].visible }).id(lambda {self.scene.target[self.index].id}).left(lambda { s = self.scene.target[self.index] w = s.width @@ -193,13 +214,13 @@ 'top' else 'bottom' end }) - + return anchor end @@ -208,15 +229,15 @@ l=s.left r=s.right t=s.top b=s.bottom prop=self.properties - w = (prop[:width] and !prop[:width].nil?) ? s.width : 0 - h = (prop[:height] and !prop[:height].nil?) ? s.height : 0 - #puts "#{l},#{r},#{t},#{b}" - #puts "#{w},#{h}" - + #p self + w = (prop[:width]) ? s.width : 0 + h = (prop[:height]) ? s.height : 0 + #puts "l:#{l},r:#{r},t:#{t},b:#{b}" + #puts "w:#{w},h:#{h}" width=self.parent ? self.parent.width(): (w+(l.nil? ? 0 : l)+(r.nil? ? 0 :r)) if w.nil? r||=0 l||=0 w=width-r-l @@ -262,27 +283,36 @@ s.height=h if prop[:height] s.text_style=Rubyvis::Color.transparent if prop[:text_style] and !s.text_style s.fill_style=Rubyvis::Color.transparent if prop[:fill_style] and !s.fill_style s.stroke_style=Rubyvis::Color.transparent if prop[:stroke_style] and !s.stroke_style end - - - - - def pr_svg(name) - res=self.send(name) - if res.nil? - "none" - else - res.to_s + def render + parent=self.parent + @stack=Mark.stack + if parent and !self.root.scene + root.render() + return end + @indexes=[] + mark=self + until mark.parent.nil? + @indexes.unshift(mark.child_index) + end + bind + while(parent and !parent.respond_to? :index) do + parent=parent.parent + end + + self.context( parent ? parent.scene : nil, parent ? parent.index : -1, lambda {render_render(self.root, 0,1)}) + end + def render_render(mark,depth,scale) mark.scale=scale if (depth < @indexes.size) @stack.unshift(nil) - if (mark.respond_to? :index) + if (mark.respond_to? :index and mark.index) render_instance(mark, depth, scale); else mark.scene.size.times {|i| mark.index = i; render_instance(mark, depth, scale); @@ -321,69 +351,55 @@ end end private :render_render, :render_instance def bind_bind(mark) begin - @_properties.each {|v| - k=v.name.to_s + mark._properties.each {|v| + #p v.name + k=v.name if !@seen.has_key?(k) @seen[k]=v case k - when "data" + when :data @_data=v - when "visible" + when :visible @_required.push(v) - when "id" + when :id @_required.push(v) else @types[v._type].push(v) end end } end while(mark = mark.proto) end + attr_accessor :binds + def bind() @seen={} @types={1=>[],2=>[],3=>[]} @_data=nil @_required=[] bind_bind(self) + bind_bind((self.class).defaults) @types[1].reverse! @types[3].reverse! mark=self begin - properties.each {|name,v| - if !@seen[name.to_s] - @seen[name.to_s]=OpenStruct.new(:name=>name.to_s, :_type=>2, :value=>nil) - @types[2].push(@seen[name.to_s]) - end - } + properties.each {|name,v| + if !@seen[name] + @seen[name]=Property.new(:name=>name, :_type=>2, :value=>nil) + @types[2].push(@seen[name]) + end + } end while(mark=mark.proto) @binds=OpenStruct.new({:properties=>@seen, :data=>@_data, :required=>@_required, :optional=>@types[1]+@types[2]+@types[3] }) end - def render - parent=self.parent - @stack=Mark.stack - if parent and !self.root.scene - root.render() - return - end - @indexes=[] - mark=self - until mark.parent.nil? - indexes.unshift(mark.child_index) - end - self.bind() - while(parent and !parent.respond_to? :index) do - parent=parent.parent - end - self.context( parent ? parent.scene : nil, parent ? parent.index : -1, lambda {render_render(self.root, 0,1)}) - - end + def context_apply(scene,index) Mark.scene=scene Mark.index=index return if(!scene) that=scene.mark @@ -453,11 +469,11 @@ end def build scene=self.scene stack=Mark.stack - #p self.type + if(!scene) self.scene=SceneElement.new scene=self.scene scene.mark=self scene.type=self.type @@ -465,24 +481,26 @@ if(self.parent) scene.parent=self.parent.scene scene.parent_index=self.parent.index end end + # Resolve anchor target + #puts "Resolve target" if(self.target) scene.target=self.target.instances(scene) end - + #pp self.binds data=self.binds.data #puts "stack:#{stack}" #puts "data_value:#{data.value}" data=(data._type & 1)>0 ? data.value.js_apply(self, stack) : data.value #puts "data:#{data}" stack.unshift(nil) scene.size=data.size - data.each_with_index {|d,i| + data.each_with_index {|d, i| Mark.index=self.index=i s=scene[i] if !s scene[i]=s=SceneElement.new end @@ -506,23 +524,23 @@ #p props props.each do |prop| v=prop.value # p "#{prop.name}=#{v}" - if prop._type==3 v=v.js_apply(self, Mark.stack) end ss.send((prop.name.to_s+"=").to_sym, v) end #p ss end end end +require 'rubyvis/mark/anchor' require 'rubyvis/mark/bar' require 'rubyvis/mark/panel' -require 'rubyvis/mark/rule' require 'rubyvis/mark/area' -require 'rubyvis/mark/anchor' +require 'rubyvis/mark/line' +require 'rubyvis/mark/rule' require 'rubyvis/mark/label'