GraphvizR 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == 0.4.0 / 2007-02-26
2
+
3
+ * default attributes for edge can be specified
4
+ * specify consective edges in one line
5
+ * speciry node rank
6
+
1
7
  == 0.3.2 / 2007-02-21
2
8
 
3
9
  * add rdoc comments
data/README.txt CHANGED
@@ -86,8 +86,6 @@ To know more detail, please see test/test_graphviz_r.rb
86
86
 
87
87
  == TODO:
88
88
 
89
- * cover all specification for graphviz
90
-
91
89
  == INSTALL:
92
90
 
93
91
  * sudo gem install graphviz_r
@@ -33,7 +33,7 @@
33
33
  # gvr = GraphvizR.new 'sample'
34
34
  # gvr.alpha >> gvr.beta
35
35
  # generates
36
- # diagraph sample {
36
+ # digraph sample {
37
37
  # alpla -> beta
38
38
  # }
39
39
  # while
@@ -44,6 +44,28 @@
44
44
  # alpla -- beta
45
45
  # }
46
46
  #
47
+ # == Grouping Nodes
48
+ #
49
+ # When one node is the root of some nodes, you can aggregate the children by using an array.
50
+ # For example,
51
+ # gvr = GraphvizR.new 'sample'
52
+ # gvr.alpha >> [gvr.beta, gvr.gamma, gvr.delta]
53
+ # generates
54
+ # digraph sample {
55
+ # alpha -> {beta; gamma; delta;}
56
+ # }
57
+ #
58
+ # == Consective Edges
59
+ #
60
+ # You can write:
61
+ # gvr = GraphvizR.new 'sample'
62
+ # gvr.alpha >> gvr.beta >> gvr.gamma >> gvr.delta
63
+ # instead of doing:
64
+ # gvr = GraphvizR.new 'sample'
65
+ # gvr.alpha >> gvr.beta
66
+ # gvr.beta >> gvr.gamma
67
+ # gvr.gamma >> gvr.delta
68
+ #
47
69
  # == Graph Attributes
48
70
  #
49
71
  # Attributes are specified by Hash in []. Thus, to set the fillcolor of a node abc, one would use
@@ -74,10 +96,17 @@
74
96
  # (gvr.node2 >> gvr.node1(:p_right)) [:label => 'record']
75
97
  # gvr.to_dot
76
98
  #
77
- # == Subgraph
99
+ # == Rank
100
+ #
101
+ # Ranks of nodes can be set as the same value for other nodes.
102
+ # gvr.rank :same, [gvr.a, gvr.b, gvr.c]
103
+ # means node a, b, and c has same rank value and generages:
104
+ # {rank = same; a; b; c;};
78
105
  #
79
- # Subgraph is a way to construct hierarchical graph in graphviz. GraphvizR allows you to use
80
- # subgraphs by means of method calling with a block which has one argument. For example,
106
+ # == Clusters
107
+ #
108
+ # Cluster is a way to construct hierarchical graph in graphviz. GraphvizR allows you to use
109
+ # clusters by means of method calling with a block which has one argument. For example,
81
110
  # gvr = GraphvizR.new 'sample'
82
111
  # gvr.cluster0 do |c0|
83
112
  # c0.graph [:color => :blue, :label => 'area 0', :style => :bold]
@@ -112,7 +141,7 @@
112
141
  # c -> f [lhead = cluster1];
113
142
  #
114
143
  class GraphvizR
115
- VERSION = '0.3.2'
144
+ VERSION = '0.4.0'
116
145
  INDENT_UNIT = ' '
117
146
 
118
147
  # This represents graphviz attributes.
@@ -122,20 +151,20 @@ class GraphvizR
122
151
  @dot = dot
123
152
  end
124
153
 
125
- def [](prop)
126
- @dot.send :"#{@name}=", prop
154
+ def [](attr)
155
+ @dot.send :"#{@name}=", attr
127
156
  end
128
157
  end
129
158
 
130
159
  # This represents graphviz node.
131
160
  class Node
132
- attr_reader :prop, :name
161
+ attr_reader :attr, :name
133
162
 
134
163
  def initialize(name, port, dot)
135
164
  @name = name
136
165
  @port = port || []
137
166
  @dot = dot
138
- @prop = {}
167
+ @attr = {}
139
168
 
140
169
  if !@port.empty? and @port[0].is_a? Array and @port[0][0].is_a? Hash
141
170
  @dot[@name] = @port[0][0]
@@ -155,15 +184,21 @@ class GraphvizR
155
184
  end
156
185
 
157
186
  def add_edge_on_dot(node)
158
- prop = @prop.merge node.prop
159
- edge = Edge.new(self, node, @dot, prop)
187
+ attr = nil
188
+ if node.is_a? Array
189
+ node = NodeGroup.new node
190
+ attr = @attr
191
+ else
192
+ attr = @attr.merge node.attr
193
+ end
194
+ edge = Edge.new([self, node], @dot, attr)
160
195
  @dot.add_edge edge
161
196
  edge
162
197
  end
163
198
 
164
- def [](prop)
165
- @dot[@name] = prop
166
- @prop.merge! prop
199
+ def [](attr)
200
+ @dot[@name] = attr
201
+ @attr.merge! attr
167
202
  self
168
203
  end
169
204
 
@@ -181,18 +216,43 @@ class GraphvizR
181
216
  name.map{|e| e.to_dot}.join(':')
182
217
  end
183
218
  end
219
+
220
+ # Aggregate some nodes.
221
+ class NodeGroup
222
+ def initialize(nodes, attr={})
223
+ @nodes = nodes
224
+ @attributes = attr
225
+ end
226
+
227
+ def to_sym
228
+ to_dot.to_sym
229
+ end
230
+
231
+ def to_dot
232
+ dot = "{"
233
+ dot += @attributes.to_a.map{|e| "#{e[0]} = #{e[1]};"}.join(' ') unless @attributes.empty?
234
+ dot += ' ' unless @attributes.empty?
235
+ dot += @nodes.map{|e| "#{e.to_dot};"}.join(' ')
236
+ dot += "}"
237
+ end
238
+ end
184
239
 
185
240
  # This represents a graphviz edge.
186
241
  class Edge
187
- def initialize(from, to, dot, prop={})
188
- @from = from
189
- @to = to
242
+ def initialize(nodes, dot, attr={})
243
+ @nodes = nodes
190
244
  @dot = dot
191
- @property = prop
245
+ @attribute = attr
192
246
  end
193
-
194
- def [](prop)
195
- @property.merge! prop
247
+
248
+ def [](attr)
249
+ @attribute.merge! attr
250
+ end
251
+
252
+ def >>(node, attr={})
253
+ @nodes << node
254
+ self[attr]
255
+ self
196
256
  end
197
257
 
198
258
  def node_to_dot(node)
@@ -200,8 +260,8 @@ class GraphvizR
200
260
  end
201
261
 
202
262
  def to_dot
203
- dot = "#{node_to_dot @from} #{@dot.directed? ? '->' : '--'} #{node_to_dot @to}"
204
- dot += " #{@property.to_dot}" unless @property.empty?
263
+ dot = @nodes.map{|e| node_to_dot e}.join " #{@dot.arrow} "
264
+ dot += " #{@attribute.to_dot}" unless @attribute.empty?
205
265
  dot
206
266
  end
207
267
 
@@ -210,20 +270,20 @@ class GraphvizR
210
270
  end
211
271
  end
212
272
 
213
- # This returns dot formatted string from given properties. To know more about <tt>prop</tt>,
273
+ # This returns dot formatted string from given attributes. To know more about <tt>attr</tt>,
214
274
  # please see GraphvizR.new .
215
- def self.dot(name, prop)
216
- GraphvizR.new(name, prop).to_dot
275
+ def self.dot(name, attr)
276
+ GraphvizR.new(name, attr).to_dot
217
277
  end
218
278
 
219
279
  # This initialzes a GraphvizR instance.
220
280
  # +name+:: the name of the graph
221
- # +prop+:: <b>!deprecated!</b> all properties for a graph can be given as a hash instance.
281
+ # +attr+:: <b>!deprecated!</b> all attributes for a graph can be given as a hash instance.
222
282
  # Please guess the contents of the hash from the test or examples below:
223
283
  # gvr = GraphvizR.dot(:sample,
224
284
  # :graph => {:size => "1.5, 2.5"},
225
285
  # :label => 'example',
226
- # :node_properties => {
286
+ # :node_attributes => {
227
287
  # :beta => {:shape => :box},
228
288
  # },
229
289
  # :alpha => :beta,
@@ -235,7 +295,7 @@ class GraphvizR
235
295
  # gvr = GraphvizR.dot(:sample,
236
296
  # :graph => {:size => "1.5, 2.5"},
237
297
  # :node => {:shape => :record},
238
- # :node_properties => {
298
+ # :node_attributes => {
239
299
  # :node1 => {:label => "<p_left> left|<p_center>center|<p_right> right"},
240
300
  # :node2 => {:label => "left|center|right"}
241
301
  # },
@@ -269,34 +329,38 @@ class GraphvizR
269
329
  # )
270
330
  # +parent+:: a parent graph is given when this graph is a subgraph.
271
331
  # +indent+:: indent level when this instance is converted to rdot.
272
- def initialize(name, prop={}, parent=nil, indent=0)
332
+ def initialize(name, attr={}, parent=nil, indent=0)
273
333
  if name.is_a? Array
274
334
  initialize(*name)
275
335
  else
276
336
  @name = name
337
+ @default_graph_attributes = {}
338
+ @default_node_attributes = {}
339
+ @default_edge_attributes = {}
340
+ @node_attributes = {}
277
341
  @edges = []
278
- @default_node_properties = {}
279
- @node_properties = {}
280
- @graph_properties = {}
281
342
  @subgraphs = []
343
+ @node_groups = []
282
344
  @indent = indent + 1
283
345
  @parent = parent
284
346
  @directed = true
285
- interprete prop
347
+ interprete attr
286
348
  end
287
349
  end
288
350
 
289
- def interprete(prop) #:nodoc:
290
- prop.each do |k, v|
351
+ def interprete(attr) #:nodoc:
352
+ attr.each do |k, v|
291
353
  case k
292
- when :node_property, :node_properties
293
- add_node_properties v
354
+ when :node_attribute, :node_attributes
355
+ add_node_attributes v
294
356
  when :graph
295
- @graph_properties.merge! v
357
+ @default_graph_attributes.merge! v
296
358
  when :label, :size, :color, :fillcolor, :style
297
- @graph_properties[k] = v
359
+ @default_graph_attributes[k] = v
298
360
  when :node
299
- @default_node_properties[k] = v
361
+ @default_node_attributes[k] = v
362
+ when :edge
363
+ @default_edge_attributes[k] = v
300
364
  when :subgraphs
301
365
  add_subgraph(v)
302
366
  else
@@ -305,9 +369,9 @@ class GraphvizR
305
369
  end
306
370
  end
307
371
 
308
- # add properties for nodes
309
- def add_node_properties(props)
310
- @node_properties = props
372
+ # add attributes for nodes
373
+ def add_node_attributes(attrs)
374
+ @node_attributes = attrs
311
375
  end
312
376
 
313
377
  # add an edge to the graph
@@ -316,19 +380,19 @@ class GraphvizR
316
380
  f = from.keys[0]
317
381
  t = from[f]
318
382
  p = to
319
- @edges << Edge.new(f, t, self, p)
383
+ @edges << Edge.new([f, t], self, p)
320
384
  elsif to.nil?
321
385
  # from is Edge instance
322
386
  @edges << from
323
387
  else
324
- @edges << Edge.new(from, to, self)
388
+ @edges << Edge.new([from, to], self)
325
389
  end
326
390
  end
327
391
 
328
392
  # add subgraph
329
393
  def add_subgraph(graphs)
330
- graphs.to_a.sort.each do |key_prop|
331
- @subgraphs << self.class.new(key_prop[0], key_prop[1], self, @indent)
394
+ graphs.to_a.sort.each do |key_attr|
395
+ @subgraphs << self.class.new(key_attr[0], key_attr[1], self, @indent)
332
396
  end
333
397
  end
334
398
 
@@ -373,6 +437,10 @@ class GraphvizR
373
437
  end
374
438
  end
375
439
 
440
+ def arrow
441
+ directed? ? '->' : '--'
442
+ end
443
+
376
444
  # When block is given, create new subgraph. Otherwise, create new node.
377
445
  def [](key, *args, &block)
378
446
  if block
@@ -384,18 +452,18 @@ class GraphvizR
384
452
  end
385
453
  end
386
454
 
387
- # set properties for a node
455
+ # set attributes for a node
388
456
  def []=(key, *args, &block)
389
- @node_properties[key] = args[0]
457
+ @node_attributes[key] = args[0]
390
458
  end
391
459
 
392
460
  [:label, :size, :color, :fillcolor, :style].each do |method|
393
461
  define_method :"#{method}=" do |v|
394
- @graph_properties[method] = v
462
+ @default_graph_attributes[method] = v
395
463
  end
396
464
  end
397
465
 
398
- # set graph properties
466
+ # set graph attributes
399
467
  def graph(*args)
400
468
  if args.empty?
401
469
  Attributes.new :graph, self
@@ -404,20 +472,26 @@ class GraphvizR
404
472
  end
405
473
  end
406
474
 
407
- # set graph properties
408
- def graph=(prop)
409
- @graph_properties.merge! prop
475
+ # set graph attributes
476
+ def graph=(attr)
477
+ @default_graph_attributes.merge! attr
478
+ end
479
+
480
+ def rank(same, nodes)
481
+ @node_groups << (NodeGroup.new nodes, {:rank => same})
410
482
  end
411
483
 
412
484
  # convert this instance to dot
413
485
  def to_dot
414
486
  graph_type = if subgraph?; 'subgraph'elsif directed?; 'digraph' else 'graph' end
415
487
  dot = indent_enter("#{graph_type} #{@name} {", true)
416
- dot += indent_enter("graph #{@graph_properties.to_dot};") unless @graph_properties.empty?
488
+ dot += indent_enter("graph #{@default_graph_attributes.to_dot};") unless @default_graph_attributes.empty?
417
489
  dot += @subgraphs.map{|e| e.to_dot}.join('') unless @subgraphs.empty?
418
- dot += properties_to_dot(@default_node_properties) unless @default_node_properties.empty?
419
- dot += properties_to_dot(@node_properties) unless @node_properties.empty?
490
+ dot += attributes_to_dot(@default_node_attributes) unless @default_node_attributes.empty?
491
+ dot += attributes_to_dot(@default_edge_attributes) unless @default_edge_attributes.empty?
492
+ dot += attributes_to_dot(@node_attributes) unless @node_attributes.empty?
420
493
  dot += @edges.sort.map{|e| indent_enter("#{e.to_dot};")}.join("")
494
+ dot += @node_groups.map{|e| indent_enter("#{e.to_dot};")}.join("")
421
495
  dot += indent_enter("}", true)
422
496
  dot
423
497
  end
@@ -466,12 +540,12 @@ class GraphvizR
466
540
 
467
541
  protected
468
542
 
469
- def properties_to_dot(hash) #:nodoc:
543
+ def attributes_to_dot(hash) #:nodoc:
470
544
  hash.to_a.sort.map{|e| indent_enter "#{e[0]} #{e[1].to_dot};"}.join()
471
545
  end
472
546
  end
473
547
 
474
- class Number #:nodoc:
548
+ class Numeric #:nodoc:
475
549
  def to_dot
476
550
  to_s
477
551
  end
@@ -20,7 +20,7 @@ class TestGraphvizR < Test::Unit::TestCase
20
20
  gvr = GraphvizR.dot(:sample,
21
21
  :graph => {:size => "1.5, 2.5"},
22
22
  :label => 'example',
23
- :node_properties => {
23
+ :node_attributes => {
24
24
  :beta => {:shape => :box},
25
25
  },
26
26
  :alpha => :beta,
@@ -70,7 +70,8 @@ digraph sample {
70
70
  gvr = GraphvizR.dot(:sample,
71
71
  :graph => {:size => "1.5, 2.5"},
72
72
  :node => {:shape => :record},
73
- :node_properties => {
73
+ :edge => {:fontsize => 24},
74
+ :node_attributes => {
74
75
  :node1 => {:label => "<p_left> left|<p_center>center|<p_right> right"},
75
76
  :node2 => {:label => "left|center|right"}
76
77
  },
@@ -84,6 +85,7 @@ digraph sample {
84
85
  digraph sample {
85
86
  graph [size = "1.5, 2.5"];
86
87
  node [shape = record];
88
+ edge [fontsize = 24];
87
89
  node1 [label = "<p_left> left|<p_center>center|<p_right> right"];
88
90
  node2 [label = "left|center|right"];
89
91
  node1 -> node2;
@@ -296,6 +298,70 @@ digraph sample {
296
298
  assert_equal <<-end_of_string, gvr.data(:dot)
297
299
  digraph sample {
298
300
  "alpha" -> "beta" [label = "label1"];
301
+ }
302
+ end_of_string
303
+ end
304
+
305
+ def test_consective_edges
306
+ gvr = GraphvizR.new 'sample'
307
+ gvr.alpha >> gvr.beta
308
+ gvr.alpha >> gvr.beta >> gvr.gamma
309
+ gvr.alpha >> gvr.beta >> gvr.gamma >> gvr.delta
310
+
311
+ assert_equal <<-end_of_string, gvr.to_dot
312
+ digraph sample {
313
+ alpha -> beta;
314
+ alpha -> beta -> gamma;
315
+ alpha -> beta -> gamma -> delta;
316
+ }
317
+ end_of_string
318
+ end
319
+
320
+ def test_node_group
321
+ gvr = GraphvizR.new 'sample'
322
+ # gvr.a >> gvr.grouping(){gvr.b, gvr.c, gvr.d}
323
+ # gvr.aa >> gvr.grouping(gvr.bb, gvr.cc, gvr.dd)
324
+ # a -> {b c d};
325
+ # aa -> {bb cc dd};
326
+ gvr.aaa >> [gvr.bbb, gvr.ccc, gvr.ddd]
327
+
328
+ assert_equal <<-end_of_string, gvr.to_dot
329
+ digraph sample {
330
+ aaa -> {bbb; ccc; ddd;};
331
+ }
332
+ end_of_string
333
+ end
334
+
335
+ def test_rank
336
+ gvr = GraphvizR.new 'sample'
337
+ gvr.graph [:size => "3, 3"]
338
+ gvr.Level_1 >> gvr.Level_2 >> gvr.Level_3
339
+ gvr.a >> gvr.b
340
+ gvr.a >> gvr.c
341
+ gvr.a >> gvr.d
342
+ gvr.b >> gvr.c
343
+ gvr.b >> gvr.e
344
+ gvr.d >> gvr.e
345
+ gvr.d >> gvr.f
346
+ #gvr.grouping(:rank => :same) {gvr.Level_1; gvr.a}
347
+ gvr.rank :same, [gvr.Level_1, gvr.a]
348
+ gvr.rank :same, [gvr.Level_2, gvr.c, gvr.b, gvr.d]
349
+ gvr.rank :same, [gvr.Level_3, gvr.e, gvr.f]
350
+
351
+ assert_equal <<-end_of_string, gvr.to_dot
352
+ digraph sample {
353
+ graph [size = "3, 3"];
354
+ Level_1 -> Level_2 -> Level_3;
355
+ a -> b;
356
+ a -> c;
357
+ a -> d;
358
+ b -> c;
359
+ b -> e;
360
+ d -> e;
361
+ d -> f;
362
+ {rank = same; Level_1; a;};
363
+ {rank = same; Level_2; c; b; d;};
364
+ {rank = same; Level_3; e; f;};
299
365
  }
300
366
  end_of_string
301
367
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: GraphvizR
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.2
7
- date: 2007-02-21 00:00:00 +09:00
6
+ version: 0.4.0
7
+ date: 2007-02-26 00:00:00 +09:00
8
8
  summary: Graphviz wrapper for Ruby and Rails
9
9
  require_paths:
10
10
  - lib
@@ -35,8 +35,8 @@ description: "Graphviz wrapper for Ruby. This can be used as a common library, a
35
35
  node1 [:label => @label1] node2 [:label => @label2] node1 >> node2
36
36
  node1(:p_left) >> node2 node2 >> node1(:p_center) (node2 >> node1(:p_right))
37
37
  [:label => 'record'] == DEPENDENCIES: * Graphviz (http://www.graphviz.org) ==
38
- TODO: * cover all specification for graphviz == INSTALL: * sudo gem install
39
- graphviz_r * if you want to use this in ruby on rails * script/plugin install
38
+ TODO: == INSTALL: * sudo gem install graphviz_r * if you want to use this in
39
+ ruby on rails * script/plugin install
40
40
  http://technohippy.net/svn/repos/graphviz_r/trunk/vendor/plugins/rdot ==
41
41
  LICENSE: (The MIT License)"
42
42
  autorequire:
@@ -92,5 +92,5 @@ dependencies:
92
92
  -
93
93
  - ">="
94
94
  - !ruby/object:Gem::Version
95
- version: 1.1.6
95
+ version: 1.2.0
96
96
  version: