rubyvis 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # = Crimeam War deaths (Grouped bar)
2
+ # Florence Nightingale used a coxcomb diagram to emphasize the number of deaths due to “preventible or mitigable zymotic diseases”. This graph shows data using a stacked bar chart.
1
3
  $:.unshift(File.dirname(__FILE__)+"/../../lib")
2
4
  require 'rubyvis'
3
5
  require 'ostruct'
@@ -1,3 +1,6 @@
1
+ # = Crimeam War deaths (Grouped bar)
2
+ # Florence Nightingale used a coxcomb diagram to emphasize the number of deaths due to “preventible or mitigable zymotic diseases”. This graph shows data using a line chart.
3
+
1
4
  $:.unshift(File.dirname(__FILE__)+"/../../lib")
2
5
  require 'rubyvis'
3
6
  require 'ostruct'
@@ -1,6 +1,6 @@
1
- # = First example
1
+ # = First example (Protovis API)
2
2
  # This is the protovis API version of "Getting Started" example of Protovis introduction.
3
- # On this example we show you how can you build a bar chart using panel and bar marks.
3
+ # On this example we build a bar chart using panel and bar marks.
4
4
  # A mark represents a set of graphical elements that share data and visual encodings. Although marks are simple by themselves, you can combine them in interesting ways to make rich, interactive visualizations
5
5
  $:.unshift(File.dirname(__FILE__)+"/../lib")
6
6
  require 'rubyvis'
@@ -1,6 +1,6 @@
1
- # = First example
1
+ # = First example (RBP API)
2
2
  # This is the RBP API version of "Getting Started" example of Protovis introduction.
3
- # On this example we show you how can you build a bar chart using panel and bar marks.
3
+ # On this example we build a bar chart using panel and bar marks.
4
4
  # A mark represents a set of graphical elements that share data and visual encodings. Although marks are simple by themselves, you can combine them in interesting ways to make rich, interactive visualizations
5
5
  $:.unshift(File.dirname(__FILE__)+"/../lib")
6
6
  require 'rubyvis'
@@ -22,11 +22,10 @@ require 'rubyvis/scene/svg_scene'
22
22
  require 'rubyvis/transform'
23
23
 
24
24
 
25
-
26
25
  module Rubyvis
27
26
  @document=nil
28
27
  # Rubyvis version
29
- VERSION = '0.2.0'
28
+ VERSION = '0.2.1'
30
29
  # Protovis API on which current Rubyvis is based
31
30
  PROTOVIS_API_VERSION='3.3'
32
31
  # You actually can do it! http://snipplr.com/view/2137/uses-for-infinity-in-ruby/
@@ -229,5 +229,34 @@ module Rubyvis
229
229
  def self.keys(map)
230
230
  map.keys
231
231
  end
232
-
232
+
233
+ # Returns a map constructed from the specified <tt>keys</tt>, using the
234
+ # function <tt>f</tt> to compute the value for each key. The single argument to
235
+ # the value function is the key. The callback is invoked only for indexes of
236
+ # the array which have assigned values; it is not invoked for indexes which
237
+ # have been deleted or which have never been assigned values.
238
+ #
239
+ # <p>For example, this expression creates a map from strings to string length:
240
+ #
241
+ # <pre>pv.dict(["one", "three", "seventeen"], function(s) s.length)</pre>
242
+ #
243
+ # The returned value is <tt>{one: 3, three: 5, seventeen: 9}</tt>. Accessor
244
+ # functions can refer to <tt>this.index</tt>.
245
+ #
246
+ # * @param {array} keys an array.
247
+ # * @param {function} f a value function.
248
+ # * @returns a map from keys to values.
249
+
250
+
251
+ def self.dict(keys, f)
252
+ m = {}
253
+ keys.size.times do |i|
254
+ unless keys[i].nil?
255
+ k=keys[i]
256
+ o=o_index(i)
257
+ m[k]=f.js_call(o,k)
258
+ end
259
+ end
260
+ m
261
+ end
233
262
  end
@@ -57,7 +57,8 @@ class Proc
57
57
  def js_apply(obj,args)
58
58
  arguments=args.dup
59
59
  # Modify numbers of args to works with arity
60
- min_args=self.arity>0 ? self.arity : (-self.arity)-1
60
+ min_args=self.arity > 0 ? self.arity : (-self.arity)-1
61
+
61
62
  if args.size > min_args and self.arity>0
62
63
  arguments=arguments[0,self.arity]
63
64
  elsif args.size < min_args
@@ -65,7 +66,12 @@ class Proc
65
66
  end
66
67
  #puts "#{args}->#{arguments} (#{self.arity})"
67
68
  if self.arity==0
68
- obj.instance_eval(&self)
69
+ if RUBY_VERSION <="1.9.2" # CHECK THIS
70
+ obj.instance_eval(&self)
71
+ else
72
+ obj.instance_exec(&self)
73
+
74
+ end
69
75
  else
70
76
  obj.instance_exec(*arguments,&self)
71
77
  end
@@ -3,7 +3,13 @@ module Rubyvis
3
3
  Rubyvis::Layout
4
4
  end
5
5
  class Layout < Rubyvis::Panel
6
- @properties=Mark.properties.dup
6
+ @properties=Panel.properties.dup
7
+ def layout_build_properties(s,properties)
8
+ mark_build_properties(s,properties)
9
+ end
10
+ def layout_build_implied(s)
11
+ panel_build_implied(s)
12
+ end
7
13
  def self.attr_accessor_dsl(*attr)
8
14
  attr.each do |sym|
9
15
  if sym.is_a? Array
@@ -74,10 +74,10 @@ module Rubyvis
74
74
  # <tt>crimea</tt>); the second argument is the layer data (a string in
75
75
  # <tt>causes</tt>). Additional arguments specify the data of enclosing panels, if any.
76
76
  class Stack < Rubyvis::Layout
77
- @properties=Panel.properties.dup
78
-
79
- attr_accessor :_x, :_y, :_values, :prop
77
+ @properties=Layout.properties.dup
80
78
  attr_accessor_dsl :orient,:offset, :order, :layers
79
+ attr_accessor :_x, :_y, :_values, :prop
80
+
81
81
  def self.defaults
82
82
  Stack.new.extend(Layout.defaults).orient("bottom-left").offset("zero").layers([[]])
83
83
  end
@@ -1,62 +1,117 @@
1
1
 
2
2
  module Rubyvis
3
- # Constructs a new mark with default properties. Marks, with the exception of
4
- # the root panel, are not typically constructed directly; instead, they are
5
- # added to a panel or an existing mark via Mark#add
6
- #
7
- # Represents a data-driven graphical mark. The +Mark+ class is
8
- # the base class for all graphical marks in Protovis; it does not provide any
9
- # specific rendering functionality, but together with Panel establishes
10
- # the core framework.
11
- #
12
- # Concrete mark types include familiar visual elements such as bars, lines
13
- # and labels. Although a bar mark may be used to construct a bar chart, marks
14
- # know nothing about charts; it is only through their specification and
15
- # composition that charts are produced. These building blocks permit many
16
- # combinatorial possibilities.
17
- #
18
- # Marks are associated with <b>data</b>: a mark is generated once per
19
- # associated datum, mapping the datum to visual <b>properties</b> such as
20
- # position and color. Thus, a single mark specification represents a set of
21
- # visual elements that share the same data and visual encoding. The type of
22
- # mark defines the names of properties and their meaning. A property may be
23
- # static, ignoring the associated datum and returning a constant; or, it may be
24
- # dynamic, derived from the associated datum or index. Such dynamic encodings
25
- # can be specified succinctly using anonymous functions. Special properties
26
- # called event handlers can be registered to add interactivity.
27
- #
28
- # Protovis uses <b>inheritance</b> to simplify the specification of related
29
- # marks: a new mark can be derived from an existing mark, inheriting its
30
- # properties. The new mark can then override properties to specify new
31
- # behavior, potentially in terms of the old behavior. In this way, the old mark
32
- # serves as the <b>prototype</b> for the new mark. Most mark types share the
33
- # same basic properties for consistency and to facilitate inheritance.
34
- #
35
- # The prioritization of redundant properties is as follows:<ol>
36
- #
37
- # <li>If the <tt>width</tt> property is not specified (i.e., null), its value
38
- # is the width of the parent panel, minus this mark's left and right margins;
39
- # the left and right margins are zero if not specified.
40
- #
41
- # <li>Otherwise, if the <tt>right</tt> margin is not specified, its value is
42
- # the width of the parent panel, minus this mark's width and left margin; the
43
- # left margin is zero if not specified.
44
- #
45
- # <li>Otherwise, if the <tt>left</tt> property is not specified, its value is
46
- # the width of the parent panel, minus this mark's width and the right margin.
47
- #
48
- # </ol>This prioritization is then duplicated for the <tt>height</tt>,
49
- # <tt>bottom</tt> and <tt>top</tt> properties, respectively.
50
- #
51
- # While most properties are <i>variable</i>, some mark types, such as lines
52
- # and areas, generate a single visual element rather than a distinct visual
53
- # element per datum. With these marks, some properties may be <b>fixed</b>.
54
- # Fixed properties can vary per mark, but not <i>per datum</i>! These
55
- # properties are evaluated solely for the first (0-index) datum, and typically
56
- # are specified as a constant. However, it is valid to use a function if the
57
- # property varies between panels or is dynamically generated.
58
- #
3
+ # Constructs a new mark with default properties. Marks, with the exception of
4
+ # the root panel, are not typically constructed directly; instead, they are
5
+ # added to a panel or an existing mark via Mark#add
6
+ #
7
+ # Represents a data-driven graphical mark. The +Mark+ class is
8
+ # the base class for all graphical marks in Protovis; it does not provide any
9
+ # specific rendering functionality, but together with Panel establishes
10
+ # the core framework.
11
+ #
12
+ # Concrete mark types include familiar visual elements such as bars, lines
13
+ # and labels. Although a bar mark may be used to construct a bar chart, marks
14
+ # know nothing about charts; it is only through their specification and
15
+ # composition that charts are produced. These building blocks permit many
16
+ # combinatorial possibilities.
17
+ #
18
+ # Marks are associated with <b>data</b>: a mark is generated once per
19
+ # associated datum, mapping the datum to visual <b>properties</b> such as
20
+ # position and color. Thus, a single mark specification represents a set of
21
+ # visual elements that share the same data and visual encoding. The type of
22
+ # mark defines the names of properties and their meaning. A property may be
23
+ # static, ignoring the associated datum and returning a constant; or, it may be
24
+ # dynamic, derived from the associated datum or index. Such dynamic encodings
25
+ # can be specified succinctly using anonymous functions. Special properties
26
+ # called event handlers can be registered to add interactivity.
27
+ #
28
+ # Protovis uses <b>inheritance</b> to simplify the specification of related
29
+ # marks: a new mark can be derived from an existing mark, inheriting its
30
+ # properties. The new mark can then override properties to specify new
31
+ # behavior, potentially in terms of the old behavior. In this way, the old mark
32
+ # serves as the <b>prototype</b> for the new mark. Most mark types share the
33
+ # same basic properties for consistency and to facilitate inheritance.
34
+ #
35
+ # The prioritization of redundant properties is as follows:<ol>
36
+ #
37
+ # <li>If the <tt>width</tt> property is not specified (i.e., null), its value
38
+ # is the width of the parent panel, minus this mark's left and right margins;
39
+ # the left and right margins are zero if not specified.
40
+ #
41
+ # <li>Otherwise, if the <tt>right</tt> margin is not specified, its value is
42
+ # the width of the parent panel, minus this mark's width and left margin; the
43
+ # left margin is zero if not specified.
44
+ #
45
+ # <li>Otherwise, if the <tt>left</tt> property is not specified, its value is
46
+ # the width of the parent panel, minus this mark's width and the right margin.
47
+ #
48
+ # </ol>This prioritization is then duplicated for the <tt>height</tt>,
49
+ # <tt>bottom</tt> and <tt>top</tt> properties, respectively.
50
+ #
51
+ # While most properties are <i>variable</i>, some mark types, such as lines
52
+ # and areas, generate a single visual element rather than a distinct visual
53
+ # element per datum. With these marks, some properties may be <b>fixed</b>.
54
+ # Fixed properties can vary per mark, but not <i>per datum</i>! These
55
+ # properties are evaluated solely for the first (0-index) datum, and typically
56
+ # are specified as a constant. However, it is valid to use a function if the
57
+ # property varies between panels or is dynamically generated.
58
+ #
59
+ # == 'RBP' API
60
+ #
61
+ # Since version 0.2.0, you could use a new API to use marks
62
+ # , similar to one described on Brown's "Ruby Best Practices".
63
+ # === Set properties using blocks
64
+ # You could use a block to set a property, without using explicitly
65
+ # lambda statement. So
66
+ # area.width {|d| d*20}
67
+ # is the same as
68
+ # area.width lambda {|d| d*20}
69
+ # === Shortcuts methods
70
+ # The protovis API uses the chain method aproach. Every method which
71
+ # set a value on a object returns the same object. I maintain
72
+ # this approach, and you can do
73
+ #
74
+ # area.width(10).height(20).top(lambda {|d| d*10})
75
+ #
76
+ # To add a mark to another, you need to use +add+ method. This methods
77
+ # returns the new mark, so you can still use the chain methods API,
78
+ #
79
+ # area.width(10).height(20). # object is 'area'
80
+ # add(Rubyvis::Label). # object changed to new label
81
+ # text('hi') # text refers to new label
82
+ #
83
+ # In the spirit of RBP, I created several methods as shortcut for +add+:
84
+ # area(), bar(), dot(), image(), label(), line(), panel(), rule() and wedge().
85
+ # If you provide a block, it will be executed inside the context of current of new mark depending on block's parameter.
86
+ # * Without parameter: block executed inside context of new mark
87
+ # * With paramenter: block executed inside context of current mark.
88
+ # Parameter references the new mark
89
+ #
90
+ # ==Example
91
+ #
92
+ # *Without parameter*
93
+ # vis=Rubyvis::Panel.new do
94
+ # area do
95
+ # width 10 # width changed for area
96
+ # height 10 # height changed for area
97
+ # end
98
+ # end
99
+ #
100
+ # *Without parameter*
101
+ # vis=Rubyvis::Panel.new do
102
+ # area do |a|
103
+ # width 10 # width changed for panel
104
+ # a.height 10 # height changed for area
105
+ # end
106
+ # end
107
+ #
59
108
  class Mark
109
+ # On ruby 1.8, we must delete #id method
110
+ # Is deprecated, so any good developer should'nt use it....
111
+ if RUBY_VERSION<"1.9"
112
+ undef_method :id
113
+ end
114
+
60
115
  # Hash storing properties names for current Mark type.
61
116
  @properties={}
62
117
 
@@ -130,7 +185,6 @@ module Rubyvis
130
185
  def self.property_method(name, _def, func=nil, klass=nil)
131
186
  return if klass.method_defined? name
132
187
  klass.send(:define_method, name) do |*arguments,&block|
133
-
134
188
  v,dummy = arguments
135
189
  if block
136
190
  v=block
@@ -200,7 +254,11 @@ module Rubyvis
200
254
  # the index is set to the instance that triggered the event.
201
255
  # @return [Integer]
202
256
  def index
203
- @index
257
+ if @index.nil?
258
+ Mark.index
259
+ else
260
+ @index
261
+ end
204
262
  end
205
263
  # Returns true if index attribute is set and not deleted
206
264
  def index_defined?
@@ -234,8 +292,8 @@ module Rubyvis
234
292
  end
235
293
 
236
294
 
237
- # @private Returns the current instance of this mark in the scene graph.
238
- # This is typically equivalent to <tt>this.scene[this.index]</tt>, however if the scene or index is unset, the default instance of the mark is returned. If no default is set, the default is the last instance.
295
+ # Returns the current instance of this mark in the scene graph.
296
+ # This is typically equivalent to +self.scene[self.index]+, however if the scene or index is unset, the default instance of the mark is returned. If no default is set, the default is the last instance.
239
297
  # Similarly, if the scene or index of the parent panel is unset, the default instance of this mark in the last instance of the enclosing panel is returned, and so on.
240
298
  #
241
299
  # @return a node in the scene graph.
@@ -243,9 +301,10 @@ module Rubyvis
243
301
  scene=self.scene
244
302
  scene||=self.parent.instance(-1).children[self.child_index]
245
303
 
246
- index = index_defined? ? self.index : default_index
247
- # "defined?: #{index_defined?} : type: #{type}, self.index: #{self.index}, index:#{index}"
248
- scene[index<0 ? scene.size-1: index]
304
+ index = !self.index.nil? ? self.index : default_index
305
+
306
+ #puts "defined?: #{index_defined?} : type: #{type}, self.index: #{self.index}, default_index: #{default_index}, index:#{index}"
307
+ scene[index < 0 ? scene.size-1: index]
249
308
  end
250
309
 
251
310
  ##
@@ -397,17 +456,15 @@ module Rubyvis
397
456
  @scale=1
398
457
  @scene=nil
399
458
  if block
400
- block.arity<1 ? self.instance_eval(&block) : block.call(self)
459
+ execute(&block)
460
+ #block.arity<1 ? self.instance_eval(&block) : block.call(self)
401
461
  end
402
462
  end
403
-
404
-
405
-
406
-
407
-
463
+ # Execute a block using this mark as a reference
464
+ def execute(&block)
408
465
 
409
-
410
-
466
+ block.arity<1 ? self.instance_eval(&block) : block.call(self)
467
+ end
411
468
  # The mark type; a lower name. The type name controls rendering
412
469
  # behavior, and unless the rendering engine is extended, must be one of the
413
470
  # built-in concrete mark types: area, bar, dot, image, label, line, panel,
@@ -467,8 +524,28 @@ module Rubyvis
467
524
  scene
468
525
  end
469
526
 
527
+
528
+ # Returns the first instance of this mark in the scene graph. This
529
+ # method can only be called when the mark is bound to the scene graph (for
530
+ # example, from an event handler, or within a property function).
531
+ #
532
+ # * @returns a node in the scene graph.
533
+ def first
534
+ scene[0]
535
+ end
536
+ # Returns the last instance of this mark in the scene graph. This
537
+ # method can only be called when the mark is bound to the scene graph (for
538
+ # example, from an event handler, or within a property function). In addition,
539
+ # note that mark instances are built sequentially, so the last instance of this
540
+ # mark may not yet be constructed.
541
+ #
542
+ # * @returns a node in the scene graph.
543
+ def last
544
+ scene[scene.size - 1]
545
+ end
470
546
 
471
- #Returns the previous instance of this mark in the scene graph, or
547
+
548
+ # Returns the previous instance of this mark in the scene graph, or
472
549
  # nil if this is the first instance.
473
550
  #
474
551
  # @return a node in the scene graph, or nil.
@@ -487,6 +564,15 @@ module Rubyvis
487
564
  s= par ? par.sibling : nil
488
565
  (s and s.children) ? s.children[self.child_index][self.index] : nil
489
566
  end
567
+
568
+ # Adds a new mark of the specified type to the enclosing parent panel,
569
+ # whilst simultaneously setting the prototype of the new mark
570
+ # to be this mark.
571
+ #
572
+ # * @param {function} type the type of mark to add; a constructor, such as
573
+ # +Rubyvis::Bar+
574
+ # * @returns {Mark} the new mark.
575
+ # * @see #extend
490
576
  def add(type)
491
577
  parent.add(type).extend(self)
492
578
  end
@@ -526,13 +612,13 @@ module Rubyvis
526
612
  a=self.scene.target.map {|s| puts "s:#{s.data}" if $DEBUG; s.data}
527
613
  p a if $DEBUG
528
614
  a
615
+ }).visible(lambda {
616
+ self.scene.target[index].visible
617
+ }).id(lambda {
618
+ self.scene.target[index].id
529
619
  }).
530
- visible(lambda {
531
- self.scene.target[self.index].visible
532
- }).
533
- id(lambda {self.scene.target[self.index].id}).
534
620
  left(lambda {
535
- s = self.scene.target[self.index]
621
+ s = self.scene.target[index]
536
622
  w = s.width
537
623
  w||=0
538
624
  if ['bottom','top','center'].include?(self.name)
@@ -577,7 +663,7 @@ module Rubyvis
577
663
  'bottom'
578
664
  end
579
665
  })
580
- return anchor
666
+ anchor
581
667
  end
582
668
 
583
669
 
@@ -685,7 +771,10 @@ module Rubyvis
685
771
  parent=parent.parent
686
772
  end
687
773
 
688
- self.context( parent ? parent.scene : nil, parent ? parent.index : -1, lambda {render_render(self.root, 0,1)})
774
+ self.context( parent ? parent.scene : nil,
775
+ parent ? parent.index : -1,
776
+ lambda { render_render(root, 0,1) }
777
+ )
689
778
 
690
779
  end
691
780
 
@@ -786,7 +875,7 @@ module Rubyvis
786
875
  end
787
876
 
788
877
 
789
- def context_apply(scene,index)
878
+ def context_apply(scene,index) # :nodoc:
790
879
  Mark.scene=scene
791
880
  Mark.index=index
792
881
  return if(!scene)
@@ -819,7 +908,7 @@ module Rubyvis
819
908
  end
820
909
 
821
910
  end
822
- def context_clear(scene,index)
911
+ def context_clear(scene,index) # :nodoc:
823
912
  return if !scene
824
913
  that=scene.mark
825
914
  mark=nil
@@ -841,7 +930,7 @@ module Rubyvis
841
930
  mark.index=nil
842
931
  end while(mark=mark.parent)
843
932
  end
844
- def context(scene,index,f)
933
+ def context(scene,index,f) # :nodoc:
845
934
  proto=Mark
846
935
  stack=Mark.stack
847
936
  oscene=Mark.scene
@@ -954,7 +1043,7 @@ module Rubyvis
954
1043
  #
955
1044
  # @param s a node in the scene graph; the instance of the mark to build.
956
1045
  # @param properties an array of properties.
957
- def build_properties(ss, props)
1046
+ def build_properties(ss, props) # :nodoc:
958
1047
  #p props
959
1048
  props.each do |prop|
960
1049
  v=prop.value
@@ -967,7 +1056,7 @@ module Rubyvis
967
1056
  end
968
1057
  end
969
1058
  # @todo implement
970
- def event(type,handler)
1059
+ def event(type,handler) # :nodoc:
971
1060
  #@_handlers[type]=handler
972
1061
  self
973
1062
  end