rubyvis 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +9 -1
- data/Manifest.txt +9 -4
- data/README.txt +59 -8
- data/examples/antibiotics/antibiotics.rb +16 -8
- data/examples/area.rb +6 -49
- data/examples/bar_column_chart.rb +4 -0
- data/examples/crimea/{crimea.rb → crimea_data.rb} +0 -0
- data/examples/crimea/crimea_grouped_bar.rb +2 -2
- data/examples/crimea/crimea_line.rb +1 -1
- data/examples/dot.rb +7 -8
- data/examples/first.rb +4 -0
- data/examples/grouped_charts.rb +3 -0
- data/examples/line.rb +19 -61
- data/examples/line_and_step.rb +4 -0
- data/examples/nested_grid.rb +53 -0
- data/examples/scatterplot.rb +2 -0
- data/examples/second.rb +14 -2
- data/examples/third.rb +9 -6
- data/lib/rubyvis/color/color.rb +8 -6
- data/lib/rubyvis/color/colors.rb +4 -6
- data/lib/rubyvis/format/number.rb +2 -2
- data/lib/rubyvis/internals.rb +15 -3
- data/lib/rubyvis/javascript_behaviour.rb +20 -8
- data/lib/rubyvis/layout/stack.rb +13 -16
- data/lib/rubyvis/mark/anchor.rb +64 -2
- data/lib/rubyvis/mark/area.rb +4 -3
- data/lib/rubyvis/mark/bar.rb +51 -2
- data/lib/rubyvis/mark/dot.rb +88 -5
- data/lib/rubyvis/mark/label.rb +94 -3
- data/lib/rubyvis/mark/line.rb +3 -2
- data/lib/rubyvis/mark/panel.rb +1 -0
- data/lib/rubyvis/mark/rule.rb +2 -1
- data/lib/rubyvis/mark/wedge.rb +2 -1
- data/lib/rubyvis/mark.rb +419 -54
- data/lib/rubyvis/nest.rb +20 -20
- data/lib/rubyvis/scale/linear.rb +1 -1
- data/lib/rubyvis/scale/log.rb +1 -1
- data/lib/rubyvis/scale/ordinal.rb +120 -8
- data/lib/rubyvis/scale/quantitative.rb +159 -15
- data/lib/rubyvis/scale.rb +1 -1
- data/lib/rubyvis/scene/svg_area.rb +12 -12
- data/lib/rubyvis/scene/svg_line.rb +5 -5
- data/lib/rubyvis/scene/svg_panel.rb +1 -1
- data/lib/rubyvis/scene/svg_scene.rb +1 -1
- data/lib/rubyvis.rb +35 -6
- data/spec/anchor_spec.rb +15 -15
- data/web/Rakefile +34 -0
- data/web/build_site.rb +86 -0
- data/web/examples.haml +26 -0
- data/web/index.haml +97 -0
- data/web/style.css +82 -0
- data.tar.gz.sig +0 -0
- metadata +14 -9
- metadata.gz.sig +0 -0
- data/lib/rubyvis/label.rb +0 -1
- data/web/first.svg +0 -1
- data/web/index.html +0 -48
data/lib/rubyvis/mark.rb
CHANGED
@@ -1,11 +1,131 @@
|
|
1
1
|
module Rubyvis
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
# Constructs a new mark with default properties. Marks, with the exception of
|
3
|
+
# the root panel, are not typically constructed directly; instead, they are
|
4
|
+
# added to a panel or an existing mark via Mark#add
|
5
|
+
#
|
6
|
+
# Represents a data-driven graphical mark. The +Mark+ class is
|
7
|
+
# the base class for all graphical marks in Protovis; it does not provide any
|
8
|
+
# specific rendering functionality, but together with Panel establishes
|
9
|
+
# the core framework.
|
10
|
+
#
|
11
|
+
# Concrete mark types include familiar visual elements such as bars, lines
|
12
|
+
# and labels. Although a bar mark may be used to construct a bar chart, marks
|
13
|
+
# know nothing about charts; it is only through their specification and
|
14
|
+
# composition that charts are produced. These building blocks permit many
|
15
|
+
# combinatorial possibilities.
|
16
|
+
#
|
17
|
+
# Marks are associated with <b>data</b>: a mark is generated once per
|
18
|
+
# associated datum, mapping the datum to visual <b>properties</b> such as
|
19
|
+
# position and color. Thus, a single mark specification represents a set of
|
20
|
+
# visual elements that share the same data and visual encoding. The type of
|
21
|
+
# mark defines the names of properties and their meaning. A property may be
|
22
|
+
# static, ignoring the associated datum and returning a constant; or, it may be
|
23
|
+
# dynamic, derived from the associated datum or index. Such dynamic encodings
|
24
|
+
# can be specified succinctly using anonymous functions. Special properties
|
25
|
+
# called event handlers can be registered to add interactivity.
|
26
|
+
#
|
27
|
+
# Protovis uses <b>inheritance</b> to simplify the specification of related
|
28
|
+
# marks: a new mark can be derived from an existing mark, inheriting its
|
29
|
+
# properties. The new mark can then override properties to specify new
|
30
|
+
# behavior, potentially in terms of the old behavior. In this way, the old mark
|
31
|
+
# serves as the <b>prototype</b> for the new mark. Most mark types share the
|
32
|
+
# same basic properties for consistency and to facilitate inheritance.
|
33
|
+
#
|
34
|
+
# The prioritization of redundant properties is as follows:<ol>
|
35
|
+
#
|
36
|
+
# <li>If the <tt>width</tt> property is not specified (i.e., null), its value
|
37
|
+
# is the width of the parent panel, minus this mark's left and right margins;
|
38
|
+
# the left and right margins are zero if not specified.
|
39
|
+
#
|
40
|
+
# <li>Otherwise, if the <tt>right</tt> margin is not specified, its value is
|
41
|
+
# the width of the parent panel, minus this mark's width and left margin; the
|
42
|
+
# left margin is zero if not specified.
|
43
|
+
#
|
44
|
+
# <li>Otherwise, if the <tt>left</tt> property is not specified, its value is
|
45
|
+
# the width of the parent panel, minus this mark's width and the right margin.
|
46
|
+
#
|
47
|
+
# </ol>This prioritization is then duplicated for the <tt>height</tt>,
|
48
|
+
# <tt>bottom</tt> and <tt>top</tt> properties, respectively.
|
49
|
+
#
|
50
|
+
# While most properties are <i>variable</i>, some mark types, such as lines
|
51
|
+
# and areas, generate a single visual element rather than a distinct visual
|
52
|
+
# element per datum. With these marks, some properties may be <b>fixed</b>.
|
53
|
+
# Fixed properties can vary per mark, but not <i>per datum</i>! These
|
54
|
+
# properties are evaluated solely for the first (0-index) datum, and typically
|
55
|
+
# are specified as a constant. However, it is valid to use a function if the
|
56
|
+
# property varies between panels or is dynamically generated.
|
57
|
+
#
|
6
58
|
class Mark
|
59
|
+
# Hash storing properties names for current Mark type.
|
7
60
|
@properties={}
|
61
|
+
|
62
|
+
# The enclosing parent panel. The parent panel is generally undefined only for the root panel; however, it is possible to create "offscreen" marks that are used only for inheritance purposes.
|
63
|
+
# @attr [Panel]
|
64
|
+
attr_accessor :parent
|
65
|
+
|
66
|
+
# The root parent panel. This may be undefined for "offscreen" marks that are
|
67
|
+
# created for inheritance purposes only.
|
68
|
+
#
|
69
|
+
# @attr [Panel]
|
70
|
+
attr_accessor :root
|
71
|
+
|
72
|
+
# The child index. -1 if the enclosing parent panel is null; otherwise, the
|
73
|
+
# zero-based index of this mark into the parent panel's <tt>children</tt>
|
74
|
+
# array.
|
75
|
+
# @attr [Number]
|
76
|
+
attr_accessor :child_index
|
77
|
+
|
78
|
+
|
79
|
+
# The scene graph. The scene graph is an array of objects; each object
|
80
|
+
# (or "node") corresponds to an instance of this mark and an element in the
|
81
|
+
# data array. The scene graph can be traversed to lookup previously-evaluated
|
82
|
+
# properties.
|
83
|
+
attr_accessor :scene
|
84
|
+
|
85
|
+
# The mark prototype, possibly undefined, from which to inherit property
|
86
|
+
# functions. The mark prototype is not necessarily of the same type as this
|
87
|
+
# mark. Any properties defined on this mark will override properties inherited
|
88
|
+
# either from the prototype or from the type-specific defaults.
|
89
|
+
# @attr [Mark]
|
90
|
+
attr_accessor :proto
|
91
|
+
|
92
|
+
# The mark anchor target, possibly undefined.
|
93
|
+
# @attr [Mark]
|
94
|
+
attr_accessor :target
|
95
|
+
|
96
|
+
# The current scale factor, based on any enclosing transforms. The current
|
97
|
+
# scale can be used to create scale-independent graphics. For example, to
|
98
|
+
# define a dot that has a radius of 10 irrespective of any zooming, say:
|
99
|
+
#
|
100
|
+
# <pre>dot.shape_radius(lambda { 10 / self.scale})</pre>
|
101
|
+
#
|
102
|
+
# Note that the stroke width and font size are defined irrespective of scale
|
103
|
+
# (i.e., in screen space) already. Also note that when a transform is applied
|
104
|
+
# to a panel, the scale affects only the child marks, not the panel itself.
|
105
|
+
# @attr [Float]
|
106
|
+
# @see Panel#transform
|
107
|
+
attr_accessor :scale
|
108
|
+
|
109
|
+
# Array with stores properties values
|
110
|
+
attr_reader :_properties
|
111
|
+
|
112
|
+
# OpenStruct which store values for scenes
|
113
|
+
attr_accessor :binds
|
8
114
|
|
115
|
+
|
116
|
+
# Defines a setter-getter for the specified property.
|
117
|
+
#
|
118
|
+
# If a cast function has been assigned to the specified property name, the
|
119
|
+
# property function is wrapped by the cast function, or, if a constant is
|
120
|
+
# specified, the constant is immediately cast. Note, however, that if the
|
121
|
+
# property value is null, the cast function is not invoked.
|
122
|
+
#
|
123
|
+
# Parameters:
|
124
|
+
# * @param [String] name the property name.
|
125
|
+
# * @param [Boolean] +def+ whether is a property or a def.
|
126
|
+
# * @param [Proc] +cast+ the cast function for this property.
|
127
|
+
# * @param [Class] +klass+ the klass on which property will be added
|
128
|
+
|
9
129
|
def self.property_method(name, _def, func=nil, klass=nil)
|
10
130
|
return if klass.method_defined? name
|
11
131
|
klass.send(:define_method, name) do |*arguments|
|
@@ -43,6 +163,7 @@ module Rubyvis
|
|
43
163
|
end
|
44
164
|
end
|
45
165
|
|
166
|
+
# Creates a dinamic property using property_method().
|
46
167
|
def self.attr_accessor_dsl(*attr)
|
47
168
|
attr.each do |sym|
|
48
169
|
if sym.is_a? Array
|
@@ -60,34 +181,58 @@ module Rubyvis
|
|
60
181
|
end
|
61
182
|
end
|
62
183
|
|
184
|
+
# Delete index
|
185
|
+
# @private
|
63
186
|
def delete_index
|
64
187
|
@index=nil
|
65
188
|
@index_defined=false
|
66
189
|
end
|
190
|
+
|
191
|
+
# The mark index. The value of this field depends on which instance (i.e.,
|
192
|
+
# which element of the data array) is currently being evaluated. During the
|
193
|
+
# build phase, the index is incremented over each datum; when handling events,
|
194
|
+
# the index is set to the instance that triggered the event.
|
195
|
+
# @return [Integer]
|
67
196
|
def index
|
68
197
|
@index
|
69
198
|
end
|
70
|
-
|
199
|
+
# Returns true if index attribute is set and not deleted
|
71
200
|
def index_defined?
|
72
201
|
@index_defined
|
73
202
|
end
|
203
|
+
# Set index attribute.
|
74
204
|
def index=(v)
|
75
205
|
@index_defined=true
|
76
206
|
@index=v
|
77
207
|
v
|
78
208
|
end
|
79
209
|
|
80
|
-
|
210
|
+
# Sets the value of the property <i>name</i> to <i>v</i>
|
81
211
|
def property_value(name,v)
|
82
212
|
prop=Property.new({:name=>name, :id=>Rubyvis.id, :value=>v})
|
83
213
|
@_properties.delete_if{|v1| v1.name==name}
|
84
214
|
@_properties.push(prop)
|
85
215
|
#@_properties_values[name]=v
|
86
|
-
|
216
|
+
prop
|
87
217
|
end
|
218
|
+
|
219
|
+
# Alias for setting the left, right, top and bottom properties simultaneously.
|
220
|
+
#
|
221
|
+
# @see Mark#left
|
222
|
+
# @see Mark#right
|
223
|
+
# @see Mark#top
|
224
|
+
# @see Mark#bottom
|
225
|
+
# @return [Mark] self
|
88
226
|
def margin(n)
|
89
227
|
self.left(n).right(n).top(n).bottom(n)
|
90
228
|
end
|
229
|
+
|
230
|
+
|
231
|
+
# @private Returns the current instance of this mark in the scene graph.
|
232
|
+
# 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.
|
233
|
+
# 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.
|
234
|
+
#
|
235
|
+
# @return a node in the scene graph.
|
91
236
|
def instance(default_index=nil)
|
92
237
|
scene=self.scene
|
93
238
|
scene||=self.parent.instance(-1).children[self.child_index]
|
@@ -97,46 +242,143 @@ module Rubyvis
|
|
97
242
|
scene[index<0 ? scene.size-1: index]
|
98
243
|
end
|
99
244
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
245
|
+
##
|
246
|
+
# :section: Marks properties
|
247
|
+
##
|
248
|
+
|
249
|
+
##
|
250
|
+
# :attr: data
|
251
|
+
# The data property; an array of objects. The size of the array determines the number of marks that will be instantiated; each element in the array will be passed to property functions to compute the property values. Typically, the data property is specified as a constant array, such as
|
252
|
+
# m.data([1, 2, 3, 4, 5])
|
253
|
+
# However, it is perfectly acceptable to define the data property as a
|
254
|
+
# proc. This function might compute the data dynamically, allowing
|
255
|
+
# different data to be used per enclosing panel. For instance, in the stacked
|
256
|
+
# area graph example (see Mark#scene), the data function on the area mark
|
257
|
+
# dereferences each series.
|
258
|
+
|
259
|
+
##
|
260
|
+
# :attr: visible
|
261
|
+
# The visible property; a boolean determining whether or not the mark instance
|
262
|
+
# is visible. If a mark instance is not visible, its other properties will not
|
263
|
+
# be evaluated. Similarly, for panels no child marks will be rendered.
|
264
|
+
|
265
|
+
##
|
266
|
+
# :attr: left
|
267
|
+
# The left margin; the distance, in pixels, between the left edge of the
|
268
|
+
# enclosing panel and the left edge of this mark. Note that in some cases this
|
269
|
+
# property may be redundant with the right property, or with the conjunction of
|
270
|
+
# right and width.
|
271
|
+
|
272
|
+
##
|
273
|
+
# :attr: right
|
274
|
+
# The right margin; the distance, in pixels, between the right edge of the
|
275
|
+
# enclosing panel and the right edge of this mark. Note that in some cases this
|
276
|
+
# property may be redundant with the left property, or with the conjunction of
|
277
|
+
# left and width.
|
278
|
+
|
279
|
+
##
|
280
|
+
# :attr: top
|
281
|
+
# The top margin; the distance, in pixels, between the top edge of the
|
282
|
+
# enclosing panel and the top edge of this mark. Note that in some cases this
|
283
|
+
# property may be redundant with the bottom property, or with the conjunction
|
284
|
+
# of bottom and height.
|
285
|
+
|
286
|
+
##
|
287
|
+
# :attr: bottom
|
288
|
+
# The bottom margin; the distance, in pixels, between the bottom edge of the
|
289
|
+
# enclosing panel and the bottom edge of this mark. Note that in some cases
|
290
|
+
# this property may be redundant with the top property, or with the conjunction
|
291
|
+
# of top and height.
|
292
|
+
|
293
|
+
##
|
294
|
+
# :attr: cursor
|
295
|
+
# The cursor property; corresponds to the CSS cursor property. This is
|
296
|
+
# typically used in conjunction with event handlers to indicate interactivity.
|
297
|
+
# See {CSS 2 cursor}[http://www.w3.org/TR/CSS2/ui.html#propdef-cursor]
|
298
|
+
|
299
|
+
##
|
300
|
+
# :attr: title
|
301
|
+
# The title property; corresponds to the HTML/SVG title property, allowing the
|
302
|
+
# general of simple plain text tooltips.
|
303
|
+
|
304
|
+
|
305
|
+
##
|
306
|
+
# :attr: events
|
307
|
+
# The events property; corresponds to the SVG pointer-events property,
|
308
|
+
# specifying how the mark should participate in mouse events. The default value
|
309
|
+
# is "painted". Supported values are:
|
310
|
+
#
|
311
|
+
# <p>"painted": The given mark may receive events when the mouse is over a
|
312
|
+
# "painted" area. The painted areas are the interior (i.e., fill) of the mark
|
313
|
+
# if a 'fillStyle' is specified, and the perimeter (i.e., stroke) of the mark
|
314
|
+
# if a 'strokeStyle' is specified.
|
315
|
+
#
|
316
|
+
# <p>"all": The given mark may receive events when the mouse is over either the
|
317
|
+
# interior (i.e., fill) or the perimeter (i.e., stroke) of the mark, regardless
|
318
|
+
# of the specified fillStyle and strokeStyle.
|
319
|
+
#
|
320
|
+
# <p>"none": The given mark may not receive events.
|
321
|
+
|
322
|
+
##
|
323
|
+
# :attr: reverse
|
324
|
+
# The reverse property; a boolean determining whether marks are ordered from
|
325
|
+
# front-to-back or back-to-front. SVG does not support explicit z-ordering;
|
326
|
+
# shapes are rendered in the order they appear. Thus, by default, marks are
|
327
|
+
# rendered in data order. Setting the reverse property to false reverses the
|
328
|
+
# order in which they are rendered; however, the properties are still evaluated
|
329
|
+
# (i.e., built) in forward order.
|
104
330
|
|
331
|
+
##
|
332
|
+
# :attr: id
|
333
|
+
# The instance identifier, for correspondence across animated transitions. If
|
334
|
+
# no identifier is specified, correspondence is determined using the mark
|
335
|
+
# index. Identifiers are not global, but local to a given mark.
|
105
336
|
|
106
|
-
|
337
|
+
#
|
338
|
+
|
339
|
+
attr_accessor_dsl :data, :visible, :left, :right, :top, :bottom, :cursor, :title, :reverse, :antialias, :events, :id
|
107
340
|
|
108
341
|
@scene=nil
|
109
342
|
@stack=[]
|
110
343
|
@index=nil
|
111
344
|
|
345
|
+
# @private Records which properties are defined on this mark type.
|
112
346
|
def self.properties
|
113
347
|
@properties
|
114
348
|
end
|
349
|
+
# Common index for all marks
|
115
350
|
def Mark.index
|
116
351
|
@index
|
117
352
|
end
|
353
|
+
|
354
|
+
# Set common index for all marks
|
118
355
|
def Mark.index=(v)
|
119
356
|
@index=v
|
120
357
|
end
|
121
|
-
|
122
|
-
|
123
|
-
|
358
|
+
# Get common scene for all marks
|
124
359
|
def self.scene
|
125
360
|
@scene
|
126
361
|
end
|
362
|
+
# Set common scene for all marks
|
127
363
|
def self.scene=(v)
|
128
364
|
@scene=v
|
129
365
|
end
|
366
|
+
|
367
|
+
|
368
|
+
# Return properties for current mark
|
130
369
|
def properties
|
131
370
|
(self.class).properties
|
132
371
|
end
|
372
|
+
# Get common stack for all marks
|
133
373
|
def Mark.stack
|
134
374
|
@stack
|
135
375
|
end
|
376
|
+
# Set common stack for all marks
|
136
377
|
def Mark.stack=(v)
|
137
378
|
@stack=v
|
138
379
|
end
|
139
380
|
|
381
|
+
# Create a new Mark
|
140
382
|
def initialize(opts=Hash.new)
|
141
383
|
@_properties=[]
|
142
384
|
opts.each {|k,v|
|
@@ -148,20 +390,39 @@ module Rubyvis
|
|
148
390
|
@index_defined = true
|
149
391
|
@scale=1
|
150
392
|
@scene=nil
|
151
|
-
|
152
393
|
end
|
394
|
+
|
395
|
+
|
396
|
+
# The mark type; a lower name. The type name controls rendering
|
397
|
+
# behavior, and unless the rendering engine is extended, must be one of the
|
398
|
+
# built-in concrete mark types: area, bar, dot, image, label, line, panel,
|
399
|
+
# rule, or wedge.
|
153
400
|
def type
|
154
401
|
"mark"
|
155
402
|
end
|
403
|
+
|
404
|
+
# Default properties for all mark types. By default, the data array is the
|
405
|
+
# parent data as a single-element array; if the data property is not
|
406
|
+
# specified, this causes each mark to be instantiated as a singleton
|
407
|
+
# with the parents datum. The visible property is true by default,
|
408
|
+
# and the reverse property is false.
|
156
409
|
def self.defaults
|
157
410
|
Mark.new({:data=>lambda {|d| [d]}, :visible=>true, :antialias=>true, :events=>'painted'})
|
158
411
|
end
|
412
|
+
|
413
|
+
# Sets the prototype of this mark to the specified mark. Any properties not
|
414
|
+
# defined on this mark may be inherited from the specified prototype mark,
|
415
|
+
# or its prototype, and so on. The prototype mark need not be the same
|
416
|
+
# type of mark as this mark. (Note that for inheritance to be useful,
|
417
|
+
# properties with the same name on different mark types should
|
418
|
+
# have equivalent meaning.)
|
159
419
|
def extend(proto)
|
160
420
|
@proto=proto
|
161
421
|
@target=proto.target
|
162
422
|
self
|
163
423
|
end
|
164
|
-
|
424
|
+
# Find the instances of this mark that match source.
|
425
|
+
# @see Anchor
|
165
426
|
def instances(source)
|
166
427
|
mark = self
|
167
428
|
_index = []
|
@@ -188,11 +449,24 @@ module Rubyvis
|
|
188
449
|
s.right = s.top = s.left = s.bottom = 0;
|
189
450
|
return [s];
|
190
451
|
end
|
191
|
-
|
452
|
+
scene
|
192
453
|
end
|
454
|
+
|
455
|
+
|
456
|
+
#Returns the previous instance of this mark in the scene graph, or
|
457
|
+
# null if this is the first instance.
|
458
|
+
#
|
459
|
+
# @return a node in the scene graph, or null.
|
193
460
|
def sibling
|
194
461
|
(self.index==0) ? nil: self.scene[self.index-1]
|
195
462
|
end
|
463
|
+
|
464
|
+
|
465
|
+
# Returns the current instance in the scene graph of this mark,
|
466
|
+
# in the previous instance of the enclosing parent panel.
|
467
|
+
# May return null if this instance could not be found.
|
468
|
+
#
|
469
|
+
# @return a node in the scene graph, or null.
|
196
470
|
def cousin
|
197
471
|
par=self.parent
|
198
472
|
s= par ? par.sibling : nil
|
@@ -201,29 +475,60 @@ module Rubyvis
|
|
201
475
|
def add(type)
|
202
476
|
parent.add(type).extend(self)
|
203
477
|
end
|
478
|
+
# Returns an anchor with the specified name. All marks support the five
|
479
|
+
# standard anchor names:
|
480
|
+
# * top
|
481
|
+
# * left
|
482
|
+
# * center
|
483
|
+
# * bottom
|
484
|
+
# * right
|
485
|
+
#
|
486
|
+
# In addition to positioning properties (left, right, top bottom), the
|
487
|
+
# anchors support text rendering properties (text-align, text-baseline).
|
488
|
+
# Text is rendered to appear inside the mark by default.
|
489
|
+
#
|
490
|
+
# To facilitate stacking, anchors are defined in terms of their opposite
|
491
|
+
# edge. For example, the top anchor defines the bottom property,
|
492
|
+
# such that the mark extends upwards; the bottom anchor instead defines
|
493
|
+
# the top property, such that the mark extends downwards. See also Layout::Stack
|
494
|
+
#
|
495
|
+
# While anchor names are typically constants, the anchor name is a true
|
496
|
+
# property, which means you can specify a function to compute the anchor name
|
497
|
+
# dynamically. See the Anchor#name property for details.
|
498
|
+
#
|
499
|
+
# @param [String] name the anchor name; either a string or a property function.
|
500
|
+
# @return [Anchor] the new anchor.
|
204
501
|
def anchor(name='center')
|
205
502
|
mark_anchor(name)
|
206
503
|
end
|
207
|
-
|
208
|
-
|
504
|
+
# Implementation of mark anchor
|
505
|
+
def mark_anchor(name="center") # :nodoc:
|
506
|
+
anchor=Rubyvis::Anchor.
|
507
|
+
new(self).
|
508
|
+
name(name).
|
509
|
+
data(lambda {
|
209
510
|
pp self.scene.target if $DEBUG
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
511
|
+
a=self.scene.target.map {|s| puts "s:#{s.data}" if $DEBUG; s.data}
|
512
|
+
p a if $DEBUG
|
513
|
+
a
|
514
|
+
}).
|
515
|
+
visible(lambda {
|
516
|
+
self.scene.target[self.index].visible
|
517
|
+
}).
|
518
|
+
id(lambda {self.scene.target[self.index].id}).
|
519
|
+
left(lambda {
|
520
|
+
s = self.scene.target[self.index]
|
521
|
+
w = s.width
|
522
|
+
w||=0
|
523
|
+
if ['bottom','top','center'].include?(self.name)
|
524
|
+
s.left + w / 2.0
|
525
|
+
elsif self.name=='left'
|
526
|
+
nil
|
527
|
+
else
|
528
|
+
s.left + w
|
529
|
+
end
|
530
|
+
}).
|
531
|
+
top(lambda {
|
227
532
|
s = self.scene.target[self.index]
|
228
533
|
h = s.height
|
229
534
|
h||= 0
|
@@ -261,12 +566,19 @@ module Rubyvis
|
|
261
566
|
end
|
262
567
|
|
263
568
|
|
264
|
-
|
265
|
-
|
569
|
+
# Computes the implied properties for this mark for the specified
|
570
|
+
# instance <tt>s</tt> in the scene graph. Implied properties are those with
|
571
|
+
# dependencies on multiple other properties; for example, the width property
|
572
|
+
# may be implied if the left and right properties are set. This method can be
|
573
|
+
# overridden by concrete mark types to define new implied properties, if
|
574
|
+
# necessary.
|
575
|
+
#
|
576
|
+
# @param s a node in the scene graph; the instance of the mark to build.
|
577
|
+
def build_implied(s) # :nodoc:
|
266
578
|
mark_build_implied(s)
|
267
579
|
end
|
268
|
-
|
269
|
-
def mark_build_implied(s)
|
580
|
+
|
581
|
+
def mark_build_implied(s) # :nodoc:
|
270
582
|
l=s.left
|
271
583
|
r=s.right
|
272
584
|
t=s.top
|
@@ -330,6 +642,17 @@ module Rubyvis
|
|
330
642
|
s.fill_style=Rubyvis::Color.transparent if prop[:fill_style] and !s.fill_style
|
331
643
|
s.stroke_style=Rubyvis::Color.transparent if prop[:stroke_style] and !s.stroke_style
|
332
644
|
end
|
645
|
+
# Renders this mark, including recursively rendering all child marks if this is
|
646
|
+
# a panel. This method finds all instances of this mark and renders them. This
|
647
|
+
# method descends recursively to the level of the mark to be rendered, finding
|
648
|
+
# all visible instances of the mark. After the marks are rendered, the scene
|
649
|
+
# and index attributes are removed from the mark to restore them to a clean
|
650
|
+
# state.
|
651
|
+
#
|
652
|
+
# <p>If an enclosing panel has an index property set (as is the case inside in
|
653
|
+
# an event handler), then only instances of this mark inside the given instance
|
654
|
+
# of the panel will be rendered; otherwise, all visible instances of the mark
|
655
|
+
# will be rendered.
|
333
656
|
def render
|
334
657
|
parent=self.parent
|
335
658
|
@stack=Mark.stack
|
@@ -351,7 +674,7 @@ module Rubyvis
|
|
351
674
|
|
352
675
|
end
|
353
676
|
|
354
|
-
def render_render(mark,depth,scale)
|
677
|
+
def render_render(mark,depth,scale) # :nodoc:
|
355
678
|
mark.scale=scale
|
356
679
|
if (depth < @indexes.size)
|
357
680
|
@stack.unshift(nil)
|
@@ -367,14 +690,14 @@ module Rubyvis
|
|
367
690
|
stack.shift
|
368
691
|
else
|
369
692
|
mark.build
|
370
|
-
|
371
|
-
|
693
|
+
Rubyvis.Scene.scale = scale;
|
694
|
+
Rubyvis.Scene.update_all(mark.scene);
|
372
695
|
end
|
373
696
|
mark.scale=nil
|
374
697
|
end
|
375
698
|
|
376
699
|
|
377
|
-
def render_instance(mark,depth,scale)
|
700
|
+
def render_instance(mark,depth,scale) # :nodoc:
|
378
701
|
s=mark.scene[mark.index]
|
379
702
|
if s.visible
|
380
703
|
child_index=@indexes[depth]
|
@@ -397,7 +720,6 @@ module Rubyvis
|
|
397
720
|
|
398
721
|
end
|
399
722
|
end
|
400
|
-
private :render_render, :render_instance
|
401
723
|
def bind_bind(mark)
|
402
724
|
begin
|
403
725
|
mark._properties.each {|v|
|
@@ -419,12 +741,14 @@ module Rubyvis
|
|
419
741
|
}
|
420
742
|
end while(mark = mark.proto)
|
421
743
|
end
|
422
|
-
|
423
|
-
|
744
|
+
private :bind_bind, :render_render, :render_instance
|
745
|
+
# @private In the bind phase, inherited property definitions are cached so they
|
746
|
+
# do not need to be queried during build.
|
424
747
|
def bind
|
425
748
|
mark_bind
|
426
749
|
end
|
427
|
-
|
750
|
+
|
751
|
+
def mark_bind() # :nodoc:
|
428
752
|
@seen={}
|
429
753
|
@types={1=>[],2=>[],3=>[]}
|
430
754
|
@_data=nil
|
@@ -517,6 +841,38 @@ module Rubyvis
|
|
517
841
|
end
|
518
842
|
end
|
519
843
|
|
844
|
+
# Evaluates properties and computes implied properties. Properties are
|
845
|
+
# stored in the Mark.scene array for each instance of this mark.
|
846
|
+
#
|
847
|
+
# As marks are built recursively, the Mark.index property is updated to
|
848
|
+
# match the current index into the data array for each mark. Note that the
|
849
|
+
# index property is only set for the mark currently being built and its
|
850
|
+
# enclosing parent panels. The index property for other marks is unset, but is
|
851
|
+
# inherited from the global +Mark+ class prototype. This allows mark
|
852
|
+
# properties to refer to properties on other marks <i>in the same panel</i>
|
853
|
+
# conveniently; however, in general it is better to reference mark instances
|
854
|
+
# specifically through the scene graph rather than depending on the magical
|
855
|
+
# behavior of Mark#index.
|
856
|
+
#
|
857
|
+
# The root scene array has a special property, <tt>data</tt>, which stores
|
858
|
+
# the current data stack. The first element in this stack is the current datum,
|
859
|
+
# followed by the datum of the enclosing parent panel, and so on. The data
|
860
|
+
# stack should not be accessed directly; instead, property functions are passed
|
861
|
+
# the current data stack as arguments.
|
862
|
+
#
|
863
|
+
# <p>The evaluation of the <tt>data</tt> and <tt>visible</tt> properties is
|
864
|
+
# special. The <tt>data</tt> property is evaluated first; unlike the other
|
865
|
+
# properties, the data stack is from the parent panel, rather than the current
|
866
|
+
# mark, since the data is not defined until the data property is evaluated.
|
867
|
+
# The <tt>visible</tt> property is subsequently evaluated for each instance;
|
868
|
+
# only if true will the {@link #buildInstance} method be called, evaluating
|
869
|
+
# other properties and recursively building the scene graph.
|
870
|
+
#
|
871
|
+
# <p>If this mark is being re-built, any old instances of this mark that no
|
872
|
+
# longer exist (because the new data array contains fewer elements) will be
|
873
|
+
# cleared using {@link #clearInstance}.
|
874
|
+
#
|
875
|
+
# @param parent the instance of the parent panel from the scene graph.
|
520
876
|
def build
|
521
877
|
scene=self.scene
|
522
878
|
stack=Mark.stack
|
@@ -563,17 +919,26 @@ module Rubyvis
|
|
563
919
|
stack.shift()
|
564
920
|
self
|
565
921
|
end
|
566
|
-
|
567
|
-
def build_instance(s)
|
922
|
+
# @private
|
923
|
+
def build_instance(s) # :nodoc:
|
568
924
|
mark_build_instance(s)
|
569
925
|
end
|
570
|
-
|
926
|
+
# @private
|
927
|
+
def mark_build_instance(s1) # :nodoc:
|
571
928
|
build_properties(s1, self.binds.required)
|
572
929
|
if s1.visible
|
573
930
|
build_properties(s1, self.binds.optional)
|
574
931
|
build_implied(s1)
|
575
932
|
end
|
576
933
|
end
|
934
|
+
|
935
|
+
|
936
|
+
|
937
|
+
# Evaluates the specified array of properties for the specified
|
938
|
+
# instance <tt>s</tt> in the scene graph.
|
939
|
+
#
|
940
|
+
# @param s a node in the scene graph; the instance of the mark to build.
|
941
|
+
# @param properties an array of properties.
|
577
942
|
def build_properties(ss, props)
|
578
943
|
#p props
|
579
944
|
props.each do |prop|
|
@@ -585,11 +950,11 @@ module Rubyvis
|
|
585
950
|
end
|
586
951
|
ss.send((prop.name.to_s+"=").to_sym, v)
|
587
952
|
end
|
588
|
-
# p ss
|
589
953
|
end
|
954
|
+
# @todo implement
|
590
955
|
def event(type,handler)
|
591
956
|
#@_handlers[type]=handler
|
592
|
-
|
957
|
+
self
|
593
958
|
end
|
594
959
|
end
|
595
960
|
end
|