3
# these glogal vars are used to make nice graph source
7
# if we don't like 4 spaces, we can change it any time
13
# options for node declaration
31
# options for edge declaration
49
# options for graph declaration
79
# a root class for any element in dot notation
80
class DOTSimpleElement
83
def initialize( params = {} )
84
@label = params['name'] ? params['name'] : ''
92
# an element that has options ( node, edge or graph )
93
class DOTElement < DOTSimpleElement
95
attr_accessor :name, :options
97
def initialize( params = {}, option_list = [] )
99
@name = params['name'] ? params['name'] : nil
100
@parent = params['parent'] ? params['parent'] : nil
102
option_list.each{ |i|
103
@options[i] = params[i] if params[i]
105
@options['label'] ||= @name if @name != 'node'
109
@options.each{ |i| yield i }
113
@options.each_pair{ |key, val| yield key, val }
116
#def parent=( thing )
117
# @parent.delete( self ) if defined?( @parent ) and @parent
123
# this is used when we build nodes that have shape=record
124
# ports don't have options :)
125
class DOTPort < DOTSimpleElement
128
def initialize( params = {} )
130
@name = params['label'] ? params['label'] : ''
133
( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
138
class DOTNode < DOTElement
140
def initialize( params = {}, option_list = NODE_OPTS )
141
super( params, option_list )
142
@ports = params['ports'] ? params['ports'] : []
146
@ports.each{ |i| yield i }
163
label = @options['shape'] != 'record' && @ports.length == 0 ?
165
t + $tab + "label = \"#{@options['label']}\"\n" :
167
t + $tab + 'label = "' + " \\\n" +
168
t + $tab2 + "#{@options['label']}| \\\n" +
171
}.join( "| \\\n" ) + " \\\n" +
172
t + $tab + '"' + "\n"
175
@options.to_a.collect{ |i|
176
i[1] && i[0] != 'label' ?
177
t + $tab + "#{i[0]} = #{i[1]}" : nil
178
}.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
184
# subgraph element is the same to graph, but has another header in dot
186
class DOTSubgraph < DOTElement
188
def initialize( params = {}, option_list = GRAPH_OPTS )
189
super( params, option_list )
190
@nodes = params['nodes'] ? params['nodes'] : []
191
@dot_string = 'subgraph'
195
@nodes.each{ |i| yield i }
211
hdr = t + "#{@dot_string} #{@name} {\n"
213
options = @options.to_a.collect{ |name, val|
214
val && name != 'label' ?
215
t + $tab + "#{name} = #{val}" :
216
name ? t + $tab + "#{name} = \"#{val}\"" : nil
217
}.compact.join( "\n" ) + "\n"
219
nodes = @nodes.collect{ |i|
221
}.join( "\n" ) + "\n"
222
hdr + options + nodes + t + "}\n"
227
class DOTDigraph < DOTSubgraph
228
def initialize( params = {}, option_list = GRAPH_OPTS )
229
super( params, option_list )
230
@dot_string = 'digraph'
235
class DOTEdge < DOTElement
236
attr_accessor :from, :to
237
def initialize( params = {}, option_list = EDGE_OPTS )
238
super( params, option_list )
239
@from = params['from'] ? params['from'] : nil
240
@to = params['to'] ? params['to'] : nil
244
t + "#{@from} -> #{to} [\n" +
245
@options.to_a.collect{ |i|
246
i[1] && i[0] != 'label' ?
247
t + $tab + "#{i[0]} = #{i[1]}" :
248
i[1] ? t + $tab + "#{i[0]} = \"#{i[1]}\"" : nil
249
}.compact.join( "\n" ) + "\n" + t + "]\n"