GraphvizR 0.3.2 → 0.4.0

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.
@@ -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: