ruby-graphviz_c 1.1.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.
Files changed (184) hide show
  1. checksums.yaml +7 -0
  2. data/.gemrc +0 -0
  3. data/.gitignore +9 -0
  4. data/.travis.yml +7 -0
  5. data/AUTHORS.rdoc +33 -0
  6. data/CHANGELOG.rdoc +287 -0
  7. data/COPYING.rdoc +133 -0
  8. data/Gemfile +4 -0
  9. data/README.rdoc +206 -0
  10. data/Rakefile +71 -0
  11. data/bin/dot2ruby +91 -0
  12. data/bin/gem2gv +165 -0
  13. data/bin/git2gv +167 -0
  14. data/bin/ruby2gv +234 -0
  15. data/bin/xml2gv +96 -0
  16. data/examples/dot/JSP.dot +52 -0
  17. data/examples/dot/balanced.dot +36 -0
  18. data/examples/dot/cluster.dot +30 -0
  19. data/examples/dot/dotgraph.dot +28 -0
  20. data/examples/dot/fsm.dot +20 -0
  21. data/examples/dot/genetic.dot +118 -0
  22. data/examples/dot/hello.dot +1 -0
  23. data/examples/dot/hello_test.rb +33 -0
  24. data/examples/dot/lion_share.dot +103 -0
  25. data/examples/dot/prof.dot +150 -0
  26. data/examples/dot/psg.dot +28 -0
  27. data/examples/dot/rank.dot +6 -0
  28. data/examples/dot/sdh.dot +284 -0
  29. data/examples/dot/siblings.dot +492 -0
  30. data/examples/dot/so-sample001.gv +30 -0
  31. data/examples/dot/so-sample002.gv +33 -0
  32. data/examples/dot/so-sample003.gv +45 -0
  33. data/examples/dot/test.dot +17 -0
  34. data/examples/dot/test_parse.rb +13 -0
  35. data/examples/dot/this_crach_with_dot_2.20.dot +24 -0
  36. data/examples/dot/unix.dot +104 -0
  37. data/examples/graphml/attributes.ext.graphml +12 -0
  38. data/examples/graphml/attributes.graphml +40 -0
  39. data/examples/graphml/cluster.graphml +75 -0
  40. data/examples/graphml/failed_graph.graphml +461 -0
  41. data/examples/graphml/hyper.graphml +29 -0
  42. data/examples/graphml/nested.graphml +54 -0
  43. data/examples/graphml/port.graphml +32 -0
  44. data/examples/graphml/simple.graphml +30 -0
  45. data/examples/hello.png +0 -0
  46. data/examples/rgv/rgv.ps +125 -0
  47. data/examples/rgv/test_rgv.rb +12 -0
  48. data/examples/sample01.rb +32 -0
  49. data/examples/sample02.rb +42 -0
  50. data/examples/sample03.rb +31 -0
  51. data/examples/sample04.rb +22 -0
  52. data/examples/sample05.rb +32 -0
  53. data/examples/sample06.rb +46 -0
  54. data/examples/sample07.rb +23 -0
  55. data/examples/sample08.rb +34 -0
  56. data/examples/sample09.rb +50 -0
  57. data/examples/sample10.rb +50 -0
  58. data/examples/sample11.rb +42 -0
  59. data/examples/sample12.rb +55 -0
  60. data/examples/sample13.rb +48 -0
  61. data/examples/sample14.rb +44 -0
  62. data/examples/sample15.rb +25 -0
  63. data/examples/sample16.rb +8 -0
  64. data/examples/sample17.rb +92 -0
  65. data/examples/sample18.rb +24 -0
  66. data/examples/sample19.rb +59 -0
  67. data/examples/sample20.rb +47 -0
  68. data/examples/sample21.rb +12 -0
  69. data/examples/sample22.rb +10 -0
  70. data/examples/sample23.rb +11 -0
  71. data/examples/sample24.rb +11 -0
  72. data/examples/sample25.rb +11 -0
  73. data/examples/sample26.rb +8 -0
  74. data/examples/sample27.rb +8 -0
  75. data/examples/sample28.rb +12 -0
  76. data/examples/sample29.rb +8 -0
  77. data/examples/sample30.rb +12 -0
  78. data/examples/sample31.rb +10 -0
  79. data/examples/sample32.rb +14 -0
  80. data/examples/sample33.rb +43 -0
  81. data/examples/sample34.rb +29 -0
  82. data/examples/sample35.rb +43 -0
  83. data/examples/sample36.rb +35 -0
  84. data/examples/sample37.rb +87 -0
  85. data/examples/sample38.rb +12 -0
  86. data/examples/sample39.rb +11 -0
  87. data/examples/sample40.rb +17 -0
  88. data/examples/sample41.rb +8 -0
  89. data/examples/sample42.rb +35 -0
  90. data/examples/sample43.rb +26 -0
  91. data/examples/sample44.rb +97 -0
  92. data/examples/sample45.rb +24 -0
  93. data/examples/sample46.rb +43 -0
  94. data/examples/sample47.rb +7 -0
  95. data/examples/sample48.rb +62 -0
  96. data/examples/sample49.rb +10 -0
  97. data/examples/sample50.rb +215 -0
  98. data/examples/sample51.rb +37 -0
  99. data/examples/sample52.rb +62 -0
  100. data/examples/sample53.rb +26 -0
  101. data/examples/sample54.rb +26 -0
  102. data/examples/sample55.rb +9 -0
  103. data/examples/sample56.rb +10 -0
  104. data/examples/sample57.rb +8 -0
  105. data/examples/sample58.rb +33 -0
  106. data/examples/sample59.rb +14 -0
  107. data/examples/sample60.rb +12 -0
  108. data/examples/sample61.rb +12 -0
  109. data/examples/sample62.rb +24 -0
  110. data/examples/sample63.rb +32 -0
  111. data/examples/sample64.rb +31 -0
  112. data/examples/sample65.rb +9 -0
  113. data/examples/sample66.rb +4 -0
  114. data/examples/sample67.rb +10 -0
  115. data/examples/sample68.rb +27 -0
  116. data/examples/sample69.rb +23 -0
  117. data/examples/sample70.rb +9 -0
  118. data/examples/sample99.rb +70 -0
  119. data/examples/sdlshapes/README +2 -0
  120. data/examples/sdlshapes/sdl.ps +655 -0
  121. data/examples/sdlshapes/sdlshapes.dot +78 -0
  122. data/examples/test.xml +26 -0
  123. data/examples/theory/pert.rb +47 -0
  124. data/examples/theory/tests.rb +87 -0
  125. data/lib/ext/gvpr/dot2ruby.g +185 -0
  126. data/lib/graphviz/attrs.rb +73 -0
  127. data/lib/graphviz/constants.rb +294 -0
  128. data/lib/graphviz/core_ext.rb +64 -0
  129. data/lib/graphviz/dot2ruby.rb +59 -0
  130. data/lib/graphviz/dot_script.rb +109 -0
  131. data/lib/graphviz/dsl.rb +67 -0
  132. data/lib/graphviz/edge.rb +197 -0
  133. data/lib/graphviz/elements.rb +39 -0
  134. data/lib/graphviz/ext.rb +17 -0
  135. data/lib/graphviz/family_tree/couple.rb +63 -0
  136. data/lib/graphviz/family_tree/generation.rb +39 -0
  137. data/lib/graphviz/family_tree/person.rb +120 -0
  138. data/lib/graphviz/family_tree/sibling.rb +13 -0
  139. data/lib/graphviz/family_tree.rb +118 -0
  140. data/lib/graphviz/graphml.rb +268 -0
  141. data/lib/graphviz/math/matrix.rb +221 -0
  142. data/lib/graphviz/node.rb +160 -0
  143. data/lib/graphviz/nothugly/nothugly.xsl +321 -0
  144. data/lib/graphviz/nothugly.rb +63 -0
  145. data/lib/graphviz/theory.rb +321 -0
  146. data/lib/graphviz/types/arrow_type.rb +32 -0
  147. data/lib/graphviz/types/color.rb +58 -0
  148. data/lib/graphviz/types/color_list.rb +24 -0
  149. data/lib/graphviz/types/esc_string.rb +20 -0
  150. data/lib/graphviz/types/gv_bool.rb +49 -0
  151. data/lib/graphviz/types/gv_double.rb +32 -0
  152. data/lib/graphviz/types/html_string.rb +18 -0
  153. data/lib/graphviz/types/lbl_string.rb +22 -0
  154. data/lib/graphviz/types/rect.rb +35 -0
  155. data/lib/graphviz/types/spline_type.rb +77 -0
  156. data/lib/graphviz/types.rb +22 -0
  157. data/lib/graphviz/utils/colors.rb +1018 -0
  158. data/lib/graphviz/utils.rb +70 -0
  159. data/lib/graphviz/xml.rb +119 -0
  160. data/lib/graphviz.rb +967 -0
  161. data/lib/ruby-graphviz.rb +1 -0
  162. data/man/dot2ruby.1 +66 -0
  163. data/man/dot2ruby.1.ronn +55 -0
  164. data/man/gem2gv.1 +60 -0
  165. data/man/gem2gv.1.ronn +47 -0
  166. data/man/git2gv.1 +48 -0
  167. data/man/git2gv.1.ronn +40 -0
  168. data/man/ruby2gv.1 +60 -0
  169. data/man/ruby2gv.1.ronn +47 -0
  170. data/man/xml2gv.1 +48 -0
  171. data/man/xml2gv.1.ronn +39 -0
  172. data/ruby-graphviz.gemspec +47 -0
  173. data/setup.rb +1585 -0
  174. data/test/helper.rb +13 -0
  175. data/test/support.rb +95 -0
  176. data/test/test_dot_script.rb +47 -0
  177. data/test/test_examples.rb +151 -0
  178. data/test/test_graph.rb +115 -0
  179. data/test/test_search.rb +29 -0
  180. data/test/test_subgraph.rb +27 -0
  181. data/test/test_theory.rb +98 -0
  182. data/test/test_types.rb +65 -0
  183. data/test/test_utils_colors.rb +52 -0
  184. metadata +301 -0
@@ -0,0 +1,67 @@
1
+ require 'graphviz'
2
+
3
+ class GraphViz::DSL
4
+ attr_accessor :graph
5
+
6
+ # Create a new graph
7
+ def initialize(name, options = {}, &block)
8
+ @graph = GraphViz.new(name, options)
9
+ instance_eval(&block) if block
10
+ end
11
+
12
+ def method_missing(sym, *args, &block) #:nodoc:
13
+ return @graph.get_graph(sym.to_s) unless @graph.get_graph(sym.to_s).nil?
14
+ return @graph.get_node(sym.to_s) unless @graph.get_node(sym.to_s).nil?
15
+ if(@graph.respond_to?(sym, true))
16
+ @graph.send(sym, *args)
17
+ elsif(block)
18
+ @graph.add_graph(GraphViz::DSL.new(sym, { :parent => @graph, :type => @graph.type }, &block).graph)
19
+ else
20
+ @graph.add_nodes(sym.to_s, *args)
21
+ end
22
+ end
23
+
24
+ # Add a new node
25
+ def n(name)
26
+ return @graph.get_node(name) unless @graph.get_node(name.to_s).nil?
27
+ @graph.add_nodes(name)
28
+ end
29
+
30
+ # Create edges
31
+ def e(*args)
32
+ e = nil
33
+ last = args.shift
34
+ while current = args.shift
35
+ e = @graph.add_edges(last, current)
36
+ last = current
37
+ end
38
+ return e
39
+ end
40
+
41
+ # Add a subgraph
42
+ def subgraph(name, &block)
43
+ @graph.add_graph(GraphViz::DSL.new(name, { :parent => @graph, :type => @graph.type }, &block).graph)
44
+ end
45
+ alias :cluster :subgraph
46
+
47
+ # Generate output
48
+ def output(options = {})
49
+ @graph.output(options)
50
+ end
51
+ end
52
+
53
+ # Create a new undirected graph
54
+ def graph(name, options = {}, &block)
55
+ GraphViz::DSL.new(name, options.merge( { :type => "graph" } ), &block).graph
56
+ end
57
+
58
+ # Create a new directed graph
59
+ def digraph(name, options = {}, &block)
60
+ GraphViz::DSL.new(name, options.merge( { :type => "digraph" } ), &block).graph
61
+ end
62
+
63
+ # Create a new strict directed graph
64
+ def strict(name, options = {}, &block)
65
+ GraphViz::DSL.new(name, options.merge( { :type => "strict digraph" } ), &block).graph
66
+ end
67
+
@@ -0,0 +1,197 @@
1
+ # Copyright (C) 2004 - 2012 Gregoire Lejeune <gregoire.lejeune@free.fr>
2
+ #
3
+ # This program is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation; either version 2 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software
15
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
+
17
+ require 'graphviz/attrs'
18
+ require 'graphviz/constants'
19
+
20
+ class GraphViz
21
+ class Edge
22
+ include GraphViz::Constants
23
+
24
+ # Create a new edge
25
+ #
26
+ # In:
27
+ # * vNodeOne : First node (can be a GraphViz::Node or a node ID)
28
+ # * vNodeTwo : Second node (can be a GraphViz::Node or a node ID)
29
+ # * parent_graph : Graph
30
+ def initialize( vNodeOne, vNodeTwo, parent_graph )
31
+ @node_one_id, @node_one_port = getNodeNameAndPort( vNodeOne )
32
+ @node_two_id, @node_two_port = getNodeNameAndPort( vNodeTwo )
33
+
34
+ @parent_graph = parent_graph
35
+ @edge_attributes = GraphViz::Attrs::new( nil, "edge", EDGESATTRS )
36
+ @index = nil
37
+
38
+ unless @parent_graph.directed?
39
+ (@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id)).incidents << (@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id))
40
+ (@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id)).neighbors << (@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id))
41
+ end
42
+ (@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id)).neighbors << (@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id))
43
+ (@parent_graph.find_node(@node_two_id) || @parent_graph.add_nodes(@node_two_id)).incidents << (@parent_graph.find_node(@node_one_id) || @parent_graph.add_nodes(@node_one_id))
44
+ end
45
+
46
+ # Return the node one as string (so with port if any)
47
+ def node_one( with_port = true )
48
+ if not(@node_one_port and with_port)
49
+ GraphViz.escape(@node_one_id)
50
+ else
51
+ GraphViz.escape(@node_one_id, :force => true) + ":#{@node_one_port}"
52
+ end
53
+ end
54
+ alias :tail_node :node_one
55
+
56
+ # Return the node two as string (so with port if any)
57
+ def node_two( with_port = true )
58
+ if not(@node_two_port and with_port)
59
+ GraphViz.escape(@node_two_id)
60
+ else
61
+ GraphViz.escape(@node_two_id, :force => true) + ":#{@node_two_port}"
62
+ end
63
+ end
64
+ alias :head_node :node_two
65
+
66
+ # Return the index of the edge
67
+ def index
68
+ @index
69
+ end
70
+ def index=(i) #:nodoc:
71
+ @index = i if @index == nil
72
+ end
73
+
74
+ # Set value +attribute_value+ to the edge attribute +attribute_name+
75
+ def []=( attribute_name, attribute_value )
76
+ attribute_value = attribute_value.to_s if attribute_value.class == Symbol
77
+ @edge_attributes[attribute_name.to_s] = attribute_value
78
+ end
79
+
80
+ # Set values for edge attributes or
81
+ # get the value of the given edge attribute +attribute_name+
82
+ def []( attribute_name )
83
+ # Modification by axgle (http://github.com/axgle)
84
+ if Hash === attribute_name
85
+ attribute_name.each do |key, value|
86
+ self[key] = value
87
+ end
88
+ else
89
+ if @edge_attributes[attribute_name.to_s]
90
+ @edge_attributes[attribute_name.to_s].clone
91
+ else
92
+ nil
93
+ end
94
+ end
95
+ end
96
+
97
+ #
98
+ # Calls block once for each attribute of the edge, passing the name and value to the
99
+ # block as a two-element array.
100
+ #
101
+ # If global is set to false, the block does not receive the attributes set globally
102
+ #
103
+ def each_attribute(global = true, &b)
104
+ attrs = @edge_attributes.to_h
105
+ if global
106
+ attrs = pg.edge.to_h.merge attrs
107
+ end
108
+ attrs.each do |k,v|
109
+ yield(k,v)
110
+ end
111
+ end
112
+ def each_attribut(global = true, &b)
113
+ warn "`GraphViz::Edge#each_attribut` is deprecated, please use `GraphViz::Edge#each_attribute`"
114
+ each_attribute(global, &b)
115
+ end
116
+
117
+ def <<( node ) #:nodoc:
118
+ n = @parent_graph.get_node(@node_two_id)
119
+
120
+ GraphViz::commonGraph( node, n ).add_edges( n, node )
121
+ end
122
+ alias :> :<< #:nodoc:
123
+ alias :- :<< #:nodoc:
124
+ alias :>> :<< #:nodoc:
125
+
126
+ #
127
+ # Return the root graph
128
+ #
129
+ def root_graph
130
+ return( (self.pg.nil?) ? nil : self.pg.root_graph )
131
+ end
132
+
133
+ def pg #:nodoc:
134
+ @parent_graph
135
+ end
136
+
137
+ # Set edge attributes
138
+ #
139
+ # Example :
140
+ # e = graph.add_edges( ... )
141
+ # ...
142
+ # e.set { |_e|
143
+ # _e.color = "blue"
144
+ # _e.fontcolor = "red"
145
+ # }
146
+ def set( &b )
147
+ yield( self )
148
+ end
149
+
150
+ # Add edge options
151
+ # use edge.<option>=<value> or edge.<option>( <value> )
152
+ def method_missing( idName, *args, &block ) #:nodoc:
153
+ return if idName == :to_ary # ruby 1.9.2 fix
154
+ xName = idName.id2name
155
+
156
+ self[xName.gsub( /=$/, "" )]=args[0]
157
+ end
158
+
159
+ def output( oGraphType ) #:nodoc:
160
+ xLink = " -> "
161
+ if oGraphType == "graph"
162
+ xLink = " -- "
163
+ end
164
+
165
+ xOut = self.node_one + xLink + self.node_two
166
+ xAttr = ""
167
+ xSeparator = ""
168
+ @edge_attributes.data.each do |k, v|
169
+ xAttr << xSeparator + k + " = " + v.to_gv
170
+ xSeparator = ", "
171
+ end
172
+ if xAttr.length > 0
173
+ xOut << " [" + xAttr + "]"
174
+ end
175
+ xOut << ";"
176
+
177
+ return( xOut )
178
+ end
179
+
180
+ private
181
+ def getNodeNameAndPort( node )
182
+ name, port = nil, nil
183
+ if node.class == Hash
184
+ node.each do |k, v|
185
+ name, port = getNodeNameAndPort(k)
186
+ port = v
187
+ end
188
+ elsif node.class == String
189
+ name = node
190
+ else
191
+ name = node.id
192
+ end
193
+
194
+ return name, port
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,39 @@
1
+ class GraphViz
2
+ class Elements
3
+ def initialize
4
+ @elements = Array.new
5
+ @elements_hash_by_type = Hash.new
6
+ end
7
+
8
+ def push( obj )
9
+ @elements.push( obj )
10
+ if @elements_hash_by_type[obj['type']].nil?
11
+ @elements_hash_by_type[obj['type']] = Array.new
12
+ end
13
+
14
+ @elements_hash_by_type[obj['type']].push( obj )
15
+ end
16
+
17
+ def each( &b )
18
+ @elements.each do |e|
19
+ yield( e )
20
+ end
21
+ end
22
+
23
+ def size_of( type )
24
+ if @elements_hash_by_type[type].nil?
25
+ return 0
26
+ else
27
+ return @elements_hash_by_type[type].size
28
+ end
29
+ end
30
+
31
+ def []( index, type = nil )
32
+ if type.nil?
33
+ return @elements[index]
34
+ else
35
+ return @elements_hash_by_type[type][index]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ require 'find'
2
+
3
+ class GraphViz
4
+ class Ext
5
+ def self.find( ext = nil )
6
+ myPath = File.join( File.dirname( File.expand_path( __FILE__ ) ), "..", "ext" )
7
+ found = myPath
8
+ unless ext.nil?
9
+ Find.find(myPath) do |path|
10
+ found = path if File.basename( path ) == ext
11
+ end
12
+ end
13
+
14
+ File.expand_path( found )
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,63 @@
1
+ class GraphViz
2
+ class FamilyTree
3
+ class Couple
4
+ def initialize( graph, node, persons ) #:nodoc:
5
+ @graph = graph
6
+ @node = node
7
+ @kids = []
8
+ @persons = persons
9
+ end
10
+
11
+ def node #:nodoc:
12
+ @node
13
+ end
14
+
15
+ # Add kids to a couple
16
+ def kids( *z )
17
+ @kids = GraphViz::FamilyTree::Sibling.new( z, @persons )
18
+
19
+ return
20
+
21
+ if z.size == 1
22
+ @graph.add_edges( @node, z[0].node, "dir" => "none" )
23
+ else
24
+ cluster = @graph.add_graph( "#{@node.id}Kids" )
25
+ cluster["rank"] = "same"
26
+
27
+ last = nil
28
+ count = 0
29
+ add = (z.size-1)%2 * z.size/2 + (z.size-1)%2
30
+ link = (z.size/2)+1
31
+
32
+ z.each do |person|
33
+ count = count + 1
34
+ if count == add
35
+ middle = cluster.add_nodes( "#{@node.id}Kids", "shape" => "point" )
36
+ @graph.add_edges( @node, middle, "dir" => "none" )
37
+ unless last.nil?
38
+ cluster.add_edges( last, middle, "dir" => "none" )
39
+ end
40
+ last = middle
41
+ end
42
+
43
+ kid = cluster.add_nodes( "#{person.node.id}Kid", "shape" => "point" )
44
+ @graph.add_edges( kid, person.node, "dir" => "none" )
45
+
46
+ if add == 0 and count == link
47
+ @graph.add_edges( @node, kid, "dir" => "none" )
48
+ end
49
+
50
+ unless last.nil?
51
+ cluster.add_edges( last, kid, "dir" => "none" )
52
+ end
53
+ last = kid
54
+ end
55
+ end
56
+ end
57
+
58
+ def getKids
59
+ @kids
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,39 @@
1
+ class GraphViz
2
+ class FamilyTree
3
+ class Generation
4
+ def initialize( graph, persons, tree, gen_number ) #:nodoc:
5
+ @graph = graph
6
+ @all_persons = persons
7
+ @persons = {}
8
+ @tree = tree
9
+ @gen_number = gen_number
10
+ end
11
+
12
+ def all_persons #:nodoc:
13
+ @all_persons
14
+ end
15
+
16
+ def persons
17
+ @persons
18
+ end
19
+
20
+ def make( &block ) #:nodoc:
21
+ instance_eval(&block) if block
22
+ end
23
+
24
+ def method_missing(sym, *args, &block) #:nodoc:
25
+ all_persons[sym.to_s] ||= (persons[sym.to_s] ||= GraphViz::FamilyTree::Person.new( @graph, @tree, self, sym.to_s ))
26
+ end
27
+
28
+ # Generation number
29
+ def number
30
+ @gen_number
31
+ end
32
+
33
+ # Generation size
34
+ def size
35
+ @persons.size
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,120 @@
1
+ require 'rubygems'
2
+ require 'graphviz'
3
+
4
+ class GraphViz
5
+ class FamilyTree
6
+ class Person
7
+ def initialize( graph, tree, generation, id ) #:nodoc:
8
+ @graph = graph
9
+ @node = @graph.add_nodes( id )
10
+ @node["shape"] = "box"
11
+ @tree = tree
12
+ @generation = generation
13
+ @x, @y = 0, 0
14
+ @sibling = nil
15
+ end
16
+
17
+ def id
18
+ @node.id
19
+ end
20
+
21
+ def name
22
+ @node.label || @node.id
23
+ end
24
+
25
+ def sibling
26
+ @sibling
27
+ end
28
+
29
+ def sibling=(x)
30
+ @sibling=x
31
+ end
32
+
33
+ def couples #:nodoc:
34
+ @couples
35
+ end
36
+
37
+ def node #:nodoc:
38
+ @node
39
+ end
40
+
41
+ # Define the current person as a man
42
+ #
43
+ # greg.is_a_man( "Greg" )
44
+ def is_a_man( name )
45
+ @node["label"] = name
46
+ @node["color"] = "blue"
47
+ end
48
+
49
+ # Define the current person as a boy
50
+ #
51
+ # greg.is_a_boy( "Greg" )
52
+ def is_a_boy( name )
53
+ is_a_man( name )
54
+ end
55
+
56
+ # Define the current perdon as a woman
57
+ #
58
+ # mu.is_a_woman( "Muriel" )
59
+ def is_a_woman( name )
60
+ @node["label"] = name
61
+ @node["color"] = "pink"
62
+ end
63
+ # Define the current perdon as a girl
64
+ #
65
+ # maia.is_a_girl( "Maia" )
66
+ def is_a_girl( name )
67
+ is_a_woman( name )
68
+ end
69
+
70
+ # Define that's two persons are maried
71
+ #
72
+ # mu.is_maried_with greg
73
+ def is_maried_with( x )
74
+ node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" )
75
+ node["shape"] = "point"
76
+ @graph.add_edges( @node, node, "dir" => "none" )
77
+ @graph.add_edges( node, x.node, "dir" => "none" )
78
+ @tree.add_couple( self, x, node )
79
+ end
80
+
81
+ # Define that's two persons are divorced
82
+ #
83
+ # sophie.is_divorced_with john
84
+ def is_divorced_with( x )
85
+ node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" )
86
+ node["shape"] = "point"
87
+ node["color"] = "red"
88
+ @graph.add_edges( @node, node, "dir" => "none", "color" => "red" )
89
+ @graph.add_edges( node, x.node, "dir" => "none", "color" => "red" )
90
+ @tree.add_couple( self, x, node )
91
+ end
92
+
93
+ # Define that's a person is widower of another
94
+ #
95
+ # simon.is_widower_of elisa
96
+ def is_widower_of( x ) #veuf
97
+ node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" )
98
+ node["shape"] = "point"
99
+ node["color"] = "green"
100
+ @graph.add_edges( @node, node, "dir" => "none", "color" => "green" )
101
+ @graph.add_edges( node, x.node, "dir" => "none", "color" => "green" )
102
+ @tree.add_couple( self, x, node )
103
+ end
104
+
105
+ # Define the current person as dead
106
+ #
107
+ # jack.is_dead
108
+ def is_dead
109
+ @node["style"] = "filled"
110
+ end
111
+
112
+ # Define the kids of a single person
113
+ #
114
+ # alice.kids( john, jack, julie )
115
+ def kids( *z )
116
+ GraphViz::FamilyTree::Couple.new( @graph, @node, [self] ).kids( *z )
117
+ end
118
+ end
119
+ end
120
+ end