Move lib/rdoc/dot/dot.rb to lib/rdoc, un-namespace.
Fix lib/rdoc/diagrom.rb for 1.9 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ecb7eb6ba4
commit
c43f867852
@ -1,3 +1,9 @@
|
|||||||
|
Fri Dec 28 16:10:00 2007 Eric Hodel <drbrain@segment7.net>
|
||||||
|
|
||||||
|
* lib/rdoc/dot/dot.rb: Move to lib/rdoc/dot.rb. Fix namespacing.
|
||||||
|
|
||||||
|
* lib/rdoc/diagram.rb: Update for 1.9.
|
||||||
|
|
||||||
Fri Dec 28 15:38:29 2007 Eric Hodel <drbrain@segment7.net>
|
Fri Dec 28 15:38:29 2007 Eric Hodel <drbrain@segment7.net>
|
||||||
|
|
||||||
* lib/rdoc/markup/sample/: Move to sample/rdoc/markup directory.
|
* lib/rdoc/markup/sample/: Move to sample/rdoc/markup directory.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# You must have the V1.7 or later in your path
|
# You must have the V1.7 or later in your path
|
||||||
# http://www.research.att.com/sw/tools/graphviz/
|
# http://www.research.att.com/sw/tools/graphviz/
|
||||||
|
|
||||||
require "rdoc/dot/dot"
|
require "rdoc/dot"
|
||||||
require 'rdoc/options'
|
require 'rdoc/options'
|
||||||
|
|
||||||
module RDoc
|
module RDoc
|
||||||
@ -55,7 +55,7 @@ module RDoc
|
|||||||
@done_modules = {}
|
@done_modules = {}
|
||||||
@local_names = find_names(i)
|
@local_names = find_names(i)
|
||||||
@global_names = []
|
@global_names = []
|
||||||
@global_graph = graph = DOT::DOTDigraph.new('name' => 'TopLevel',
|
@global_graph = graph = DOT::Digraph.new('name' => 'TopLevel',
|
||||||
'fontname' => FONT,
|
'fontname' => FONT,
|
||||||
'fontsize' => '8',
|
'fontsize' => '8',
|
||||||
'bgcolor' => 'lightcyan1',
|
'bgcolor' => 'lightcyan1',
|
||||||
@ -63,7 +63,7 @@ module RDoc
|
|||||||
|
|
||||||
# it's a little hack %) i'm too lazy to create a separate class
|
# it's a little hack %) i'm too lazy to create a separate class
|
||||||
# for default node
|
# for default node
|
||||||
graph << DOT::DOTNode.new('name' => 'node',
|
graph << DOT::Node.new('name' => 'node',
|
||||||
'fontname' => FONT,
|
'fontname' => FONT,
|
||||||
'color' => 'black',
|
'color' => 'black',
|
||||||
'fontsize' => 8)
|
'fontsize' => 8)
|
||||||
@ -82,13 +82,13 @@ module RDoc
|
|||||||
@local_names = find_names(mod)
|
@local_names = find_names(mod)
|
||||||
@global_names = []
|
@global_names = []
|
||||||
|
|
||||||
@global_graph = graph = DOT::DOTDigraph.new('name' => 'TopLevel',
|
@global_graph = graph = DOT::Digraph.new('name' => 'TopLevel',
|
||||||
'fontname' => FONT,
|
'fontname' => FONT,
|
||||||
'fontsize' => '8',
|
'fontsize' => '8',
|
||||||
'bgcolor' => 'lightcyan1',
|
'bgcolor' => 'lightcyan1',
|
||||||
'compound' => 'true')
|
'compound' => 'true')
|
||||||
|
|
||||||
graph << DOT::DOTNode.new('name' => 'node',
|
graph << DOT::Node.new('name' => 'node',
|
||||||
'fontname' => FONT,
|
'fontname' => FONT,
|
||||||
'color' => 'black',
|
'color' => 'black',
|
||||||
'fontsize' => 8)
|
'fontsize' => 8)
|
||||||
@ -127,7 +127,7 @@ module RDoc
|
|||||||
|
|
||||||
@counter += 1
|
@counter += 1
|
||||||
url = mod.http_url("classes")
|
url = mod.http_url("classes")
|
||||||
m = DOT::DOTSubgraph.new('name' => "cluster_#{mod.full_name.gsub( /:/,'_' )}",
|
m = DOT::Subgraph.new('name' => "cluster_#{mod.full_name.gsub( /:/,'_' )}",
|
||||||
'label' => mod.name,
|
'label' => mod.name,
|
||||||
'fontname' => FONT,
|
'fontname' => FONT,
|
||||||
'color' => 'blue',
|
'color' => 'blue',
|
||||||
@ -143,7 +143,7 @@ module RDoc
|
|||||||
mod.includes.each do |inc|
|
mod.includes.each do |inc|
|
||||||
m_full_name = find_full_name(inc.name, mod)
|
m_full_name = find_full_name(inc.name, mod)
|
||||||
if @local_names.include?(m_full_name)
|
if @local_names.include?(m_full_name)
|
||||||
@global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'to' => "#{mod.full_name.gsub( /:/,'_' )}",
|
'to' => "#{mod.full_name.gsub( /:/,'_' )}",
|
||||||
'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}",
|
'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
|
'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
|
||||||
@ -151,13 +151,13 @@ module RDoc
|
|||||||
unless @global_names.include?(m_full_name)
|
unless @global_names.include?(m_full_name)
|
||||||
path = m_full_name.split("::")
|
path = m_full_name.split("::")
|
||||||
url = File.join('classes', *path) + ".html"
|
url = File.join('classes', *path) + ".html"
|
||||||
@global_graph << DOT::DOTNode.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Node.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'shape' => 'box',
|
'shape' => 'box',
|
||||||
'label' => "#{m_full_name}",
|
'label' => "#{m_full_name}",
|
||||||
'URL' => %{"#{url}"})
|
'URL' => %{"#{url}"})
|
||||||
@global_names << m_full_name
|
@global_names << m_full_name
|
||||||
end
|
end
|
||||||
@global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'to' => "#{mod.full_name.gsub( /:/,'_' )}",
|
'to' => "#{mod.full_name.gsub( /:/,'_' )}",
|
||||||
'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
|
'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
|
||||||
end
|
end
|
||||||
@ -173,7 +173,7 @@ module RDoc
|
|||||||
|
|
||||||
# create dummy node (needed if empty and for module includes)
|
# create dummy node (needed if empty and for module includes)
|
||||||
if container.full_name
|
if container.full_name
|
||||||
graph << DOT::DOTNode.new('name' => "#{container.full_name.gsub( /:/,'_' )}",
|
graph << DOT::Node.new('name' => "#{container.full_name.gsub( /:/,'_' )}",
|
||||||
'label' => "",
|
'label' => "",
|
||||||
'width' => (container.classes.empty? and
|
'width' => (container.classes.empty? and
|
||||||
container.modules.empty?) ?
|
container.modules.empty?) ?
|
||||||
@ -187,7 +187,7 @@ module RDoc
|
|||||||
if use_fileboxes && !files.include?(last_file)
|
if use_fileboxes && !files.include?(last_file)
|
||||||
@counter += 1
|
@counter += 1
|
||||||
files[last_file] =
|
files[last_file] =
|
||||||
DOT::DOTSubgraph.new('name' => "cluster_#{@counter}",
|
DOT::Subgraph.new('name' => "cluster_#{@counter}",
|
||||||
'label' => "#{last_file}",
|
'label' => "#{last_file}",
|
||||||
'fontname' => FONT,
|
'fontname' => FONT,
|
||||||
'color'=>
|
'color'=>
|
||||||
@ -217,7 +217,7 @@ module RDoc
|
|||||||
'URL' => %{"#{url}"}
|
'URL' => %{"#{url}"}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = DOT::DOTNode.new(attrs)
|
c = DOT::Node.new(attrs)
|
||||||
|
|
||||||
if use_fileboxes
|
if use_fileboxes
|
||||||
files[last_file].push c
|
files[last_file].push c
|
||||||
@ -237,20 +237,20 @@ module RDoc
|
|||||||
cl.includes.each do |m|
|
cl.includes.each do |m|
|
||||||
m_full_name = find_full_name(m.name, cl)
|
m_full_name = find_full_name(m.name, cl)
|
||||||
if @local_names.include?(m_full_name)
|
if @local_names.include?(m_full_name)
|
||||||
@global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'to' => "#{cl.full_name.gsub( /:/,'_' )}",
|
'to' => "#{cl.full_name.gsub( /:/,'_' )}",
|
||||||
'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}")
|
'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}")
|
||||||
else
|
else
|
||||||
unless @global_names.include?(m_full_name)
|
unless @global_names.include?(m_full_name)
|
||||||
path = m_full_name.split("::")
|
path = m_full_name.split("::")
|
||||||
url = File.join('classes', *path) + ".html"
|
url = File.join('classes', *path) + ".html"
|
||||||
@global_graph << DOT::DOTNode.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Node.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'shape' => 'box',
|
'shape' => 'box',
|
||||||
'label' => "#{m_full_name}",
|
'label' => "#{m_full_name}",
|
||||||
'URL' => %{"#{url}"})
|
'URL' => %{"#{url}"})
|
||||||
@global_names << m_full_name
|
@global_names << m_full_name
|
||||||
end
|
end
|
||||||
@global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
|
||||||
'to' => "#{cl.full_name.gsub( /:/, '_')}")
|
'to' => "#{cl.full_name.gsub( /:/, '_')}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -261,13 +261,13 @@ module RDoc
|
|||||||
unless @local_names.include?(sclass_full_name) or @global_names.include?(sclass_full_name)
|
unless @local_names.include?(sclass_full_name) or @global_names.include?(sclass_full_name)
|
||||||
path = sclass_full_name.split("::")
|
path = sclass_full_name.split("::")
|
||||||
url = File.join('classes', *path) + ".html"
|
url = File.join('classes', *path) + ".html"
|
||||||
@global_graph << DOT::DOTNode.new(
|
@global_graph << DOT::Node.new(
|
||||||
'name' => "#{sclass_full_name.gsub( /:/, '_' )}",
|
'name' => "#{sclass_full_name.gsub( /:/, '_' )}",
|
||||||
'label' => sclass_full_name,
|
'label' => sclass_full_name,
|
||||||
'URL' => %{"#{url}"})
|
'URL' => %{"#{url}"})
|
||||||
@global_names << sclass_full_name
|
@global_names << sclass_full_name
|
||||||
end
|
end
|
||||||
@global_graph << DOT::DOTEdge.new('from' => "#{sclass_full_name.gsub( /:/,'_' )}",
|
@global_graph << DOT::Edge.new('from' => "#{sclass_full_name.gsub( /:/,'_' )}",
|
||||||
'to' => "#{cl.full_name.gsub( /:/, '_')}")
|
'to' => "#{cl.full_name.gsub( /:/, '_')}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -313,7 +313,7 @@ module RDoc
|
|||||||
def wrap_in_image_map(src, dot)
|
def wrap_in_image_map(src, dot)
|
||||||
res = %{<map id="map" name="map">\n}
|
res = %{<map id="map" name="map">\n}
|
||||||
dot_map = `dot -Tismap #{src}`
|
dot_map = `dot -Tismap #{src}`
|
||||||
dot_map.each do |area|
|
dot_map.split($/).each do |area|
|
||||||
unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
|
unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
|
||||||
$stderr.puts "Unexpected output from dot:\n#{area}"
|
$stderr.puts "Unexpected output from dot:\n#{area}"
|
||||||
return nil
|
return nil
|
||||||
|
247
lib/rdoc/dot.rb
Normal file
247
lib/rdoc/dot.rb
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
module DOT
|
||||||
|
|
||||||
|
TAB = ' '
|
||||||
|
TAB2 = TAB * 2
|
||||||
|
|
||||||
|
# options for node declaration
|
||||||
|
NODE_OPTS = [
|
||||||
|
'bgcolor',
|
||||||
|
'color',
|
||||||
|
'fontcolor',
|
||||||
|
'fontname',
|
||||||
|
'fontsize',
|
||||||
|
'height',
|
||||||
|
'width',
|
||||||
|
'label',
|
||||||
|
'layer',
|
||||||
|
'rank',
|
||||||
|
'shape',
|
||||||
|
'shapefile',
|
||||||
|
'style',
|
||||||
|
'URL',
|
||||||
|
]
|
||||||
|
|
||||||
|
# options for edge declaration
|
||||||
|
EDGE_OPTS = [
|
||||||
|
'color',
|
||||||
|
'decorate',
|
||||||
|
'dir',
|
||||||
|
'fontcolor',
|
||||||
|
'fontname',
|
||||||
|
'fontsize',
|
||||||
|
'id',
|
||||||
|
'label',
|
||||||
|
'layer',
|
||||||
|
'lhead',
|
||||||
|
'ltail',
|
||||||
|
'minlen',
|
||||||
|
'style',
|
||||||
|
'weight'
|
||||||
|
]
|
||||||
|
|
||||||
|
# options for graph declaration
|
||||||
|
GRAPH_OPTS = [
|
||||||
|
'bgcolor',
|
||||||
|
'center',
|
||||||
|
'clusterrank',
|
||||||
|
'color',
|
||||||
|
'compound',
|
||||||
|
'concentrate',
|
||||||
|
'fillcolor',
|
||||||
|
'fontcolor',
|
||||||
|
'fontname',
|
||||||
|
'fontsize',
|
||||||
|
'label',
|
||||||
|
'layerseq',
|
||||||
|
'margin',
|
||||||
|
'mclimit',
|
||||||
|
'nodesep',
|
||||||
|
'nslimit',
|
||||||
|
'ordering',
|
||||||
|
'orientation',
|
||||||
|
'page',
|
||||||
|
'rank',
|
||||||
|
'rankdir',
|
||||||
|
'ranksep',
|
||||||
|
'ratio',
|
||||||
|
'size',
|
||||||
|
'style',
|
||||||
|
'URL'
|
||||||
|
]
|
||||||
|
|
||||||
|
# a root class for any element in dot notation
|
||||||
|
class SimpleElement
|
||||||
|
attr_accessor :name
|
||||||
|
|
||||||
|
def initialize( params = {} )
|
||||||
|
@label = params['name'] ? params['name'] : ''
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
@name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# an element that has options ( node, edge or graph )
|
||||||
|
class Element < SimpleElement
|
||||||
|
#attr_reader :parent
|
||||||
|
attr_accessor :name, :options
|
||||||
|
|
||||||
|
def initialize( params = {}, option_list = [] )
|
||||||
|
super( params )
|
||||||
|
@name = params['name'] ? params['name'] : nil
|
||||||
|
@parent = params['parent'] ? params['parent'] : nil
|
||||||
|
@options = {}
|
||||||
|
option_list.each{ |i|
|
||||||
|
@options[i] = params[i] if params[i]
|
||||||
|
}
|
||||||
|
@options['label'] ||= @name if @name != 'node'
|
||||||
|
end
|
||||||
|
|
||||||
|
def each_option
|
||||||
|
@options.each{ |i| yield i }
|
||||||
|
end
|
||||||
|
|
||||||
|
def each_option_pair
|
||||||
|
@options.each_pair{ |key, val| yield key, val }
|
||||||
|
end
|
||||||
|
|
||||||
|
#def parent=( thing )
|
||||||
|
# @parent.delete( self ) if defined?( @parent ) and @parent
|
||||||
|
# @parent = thing
|
||||||
|
#end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# this is used when we build nodes that have shape=record
|
||||||
|
# ports don't have options :)
|
||||||
|
class Port < SimpleElement
|
||||||
|
attr_accessor :label
|
||||||
|
|
||||||
|
def initialize( params = {} )
|
||||||
|
super( params )
|
||||||
|
@name = params['label'] ? params['label'] : ''
|
||||||
|
end
|
||||||
|
def to_s
|
||||||
|
( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# node element
|
||||||
|
class Node < Element
|
||||||
|
|
||||||
|
def initialize( params = {}, option_list = NODE_OPTS )
|
||||||
|
super( params, option_list )
|
||||||
|
@ports = params['ports'] ? params['ports'] : []
|
||||||
|
end
|
||||||
|
|
||||||
|
def each_port
|
||||||
|
@ports.each{ |i| yield i }
|
||||||
|
end
|
||||||
|
|
||||||
|
def << ( thing )
|
||||||
|
@ports << thing
|
||||||
|
end
|
||||||
|
|
||||||
|
def push ( thing )
|
||||||
|
@ports.push( thing )
|
||||||
|
end
|
||||||
|
|
||||||
|
def pop
|
||||||
|
@ports.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s( t = '' )
|
||||||
|
|
||||||
|
label = @options['shape'] != 'record' && @ports.length == 0 ?
|
||||||
|
@options['label'] ?
|
||||||
|
t + TAB + "label = \"#{@options['label']}\"\n" :
|
||||||
|
'' :
|
||||||
|
t + TAB + 'label = "' + " \\\n" +
|
||||||
|
t + TAB2 + "#{@options['label']}| \\\n" +
|
||||||
|
@ports.collect{ |i|
|
||||||
|
t + TAB2 + i.to_s
|
||||||
|
}.join( "| \\\n" ) + " \\\n" +
|
||||||
|
t + TAB + '"' + "\n"
|
||||||
|
|
||||||
|
t + "#{@name} [\n" +
|
||||||
|
@options.to_a.collect{ |i|
|
||||||
|
i[1] && i[0] != 'label' ?
|
||||||
|
t + TAB + "#{i[0]} = #{i[1]}" : nil
|
||||||
|
}.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
|
||||||
|
label +
|
||||||
|
t + "]\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# subgraph element is the same to graph, but has another header in dot
|
||||||
|
# notation
|
||||||
|
class Subgraph < Element
|
||||||
|
|
||||||
|
def initialize( params = {}, option_list = GRAPH_OPTS )
|
||||||
|
super( params, option_list )
|
||||||
|
@nodes = params['nodes'] ? params['nodes'] : []
|
||||||
|
@dot_string = 'subgraph'
|
||||||
|
end
|
||||||
|
|
||||||
|
def each_node
|
||||||
|
@nodes.each{ |i| yield i }
|
||||||
|
end
|
||||||
|
|
||||||
|
def << ( thing )
|
||||||
|
@nodes << thing
|
||||||
|
end
|
||||||
|
|
||||||
|
def push( thing )
|
||||||
|
@nodes.push( thing )
|
||||||
|
end
|
||||||
|
|
||||||
|
def pop
|
||||||
|
@nodes.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s( t = '' )
|
||||||
|
hdr = t + "#{@dot_string} #{@name} {\n"
|
||||||
|
|
||||||
|
options = @options.to_a.collect{ |name, val|
|
||||||
|
val && name != 'label' ?
|
||||||
|
t + TAB + "#{name} = #{val}" :
|
||||||
|
name ? t + TAB + "#{name} = \"#{val}\"" : nil
|
||||||
|
}.compact.join( "\n" ) + "\n"
|
||||||
|
|
||||||
|
nodes = @nodes.collect{ |i|
|
||||||
|
i.to_s( t + TAB )
|
||||||
|
}.join( "\n" ) + "\n"
|
||||||
|
hdr + options + nodes + t + "}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# this is graph
|
||||||
|
class Digraph < Subgraph
|
||||||
|
def initialize( params = {}, option_list = GRAPH_OPTS )
|
||||||
|
super( params, option_list )
|
||||||
|
@dot_string = 'digraph'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# this is edge
|
||||||
|
class Edge < Element
|
||||||
|
attr_accessor :from, :to
|
||||||
|
def initialize( params = {}, option_list = EDGE_OPTS )
|
||||||
|
super( params, option_list )
|
||||||
|
@from = params['from'] ? params['from'] : nil
|
||||||
|
@to = params['to'] ? params['to'] : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s( t = '' )
|
||||||
|
t + "#{@from} -> #{to} [\n" +
|
||||||
|
@options.to_a.collect{ |i|
|
||||||
|
i[1] && i[0] != 'label' ?
|
||||||
|
t + TAB + "#{i[0]} = #{i[1]}" :
|
||||||
|
i[1] ? t + TAB + "#{i[0]} = \"#{i[1]}\"" : nil
|
||||||
|
}.compact.join( "\n" ) + "\n" + t + "]\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -1,255 +0,0 @@
|
|||||||
module DOT
|
|
||||||
|
|
||||||
# these glogal vars are used to make nice graph source
|
|
||||||
$tab = ' '
|
|
||||||
$tab2 = $tab * 2
|
|
||||||
|
|
||||||
# if we don't like 4 spaces, we can change it any time
|
|
||||||
def change_tab( t )
|
|
||||||
$tab = t
|
|
||||||
$tab2 = t * 2
|
|
||||||
end
|
|
||||||
|
|
||||||
# options for node declaration
|
|
||||||
NODE_OPTS = [
|
|
||||||
'bgcolor',
|
|
||||||
'color',
|
|
||||||
'fontcolor',
|
|
||||||
'fontname',
|
|
||||||
'fontsize',
|
|
||||||
'height',
|
|
||||||
'width',
|
|
||||||
'label',
|
|
||||||
'layer',
|
|
||||||
'rank',
|
|
||||||
'shape',
|
|
||||||
'shapefile',
|
|
||||||
'style',
|
|
||||||
'URL',
|
|
||||||
]
|
|
||||||
|
|
||||||
# options for edge declaration
|
|
||||||
EDGE_OPTS = [
|
|
||||||
'color',
|
|
||||||
'decorate',
|
|
||||||
'dir',
|
|
||||||
'fontcolor',
|
|
||||||
'fontname',
|
|
||||||
'fontsize',
|
|
||||||
'id',
|
|
||||||
'label',
|
|
||||||
'layer',
|
|
||||||
'lhead',
|
|
||||||
'ltail',
|
|
||||||
'minlen',
|
|
||||||
'style',
|
|
||||||
'weight'
|
|
||||||
]
|
|
||||||
|
|
||||||
# options for graph declaration
|
|
||||||
GRAPH_OPTS = [
|
|
||||||
'bgcolor',
|
|
||||||
'center',
|
|
||||||
'clusterrank',
|
|
||||||
'color',
|
|
||||||
'compound',
|
|
||||||
'concentrate',
|
|
||||||
'fillcolor',
|
|
||||||
'fontcolor',
|
|
||||||
'fontname',
|
|
||||||
'fontsize',
|
|
||||||
'label',
|
|
||||||
'layerseq',
|
|
||||||
'margin',
|
|
||||||
'mclimit',
|
|
||||||
'nodesep',
|
|
||||||
'nslimit',
|
|
||||||
'ordering',
|
|
||||||
'orientation',
|
|
||||||
'page',
|
|
||||||
'rank',
|
|
||||||
'rankdir',
|
|
||||||
'ranksep',
|
|
||||||
'ratio',
|
|
||||||
'size',
|
|
||||||
'style',
|
|
||||||
'URL'
|
|
||||||
]
|
|
||||||
|
|
||||||
# a root class for any element in dot notation
|
|
||||||
class DOTSimpleElement
|
|
||||||
attr_accessor :name
|
|
||||||
|
|
||||||
def initialize( params = {} )
|
|
||||||
@label = params['name'] ? params['name'] : ''
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
@name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# an element that has options ( node, edge or graph )
|
|
||||||
class DOTElement < DOTSimpleElement
|
|
||||||
#attr_reader :parent
|
|
||||||
attr_accessor :name, :options
|
|
||||||
|
|
||||||
def initialize( params = {}, option_list = [] )
|
|
||||||
super( params )
|
|
||||||
@name = params['name'] ? params['name'] : nil
|
|
||||||
@parent = params['parent'] ? params['parent'] : nil
|
|
||||||
@options = {}
|
|
||||||
option_list.each{ |i|
|
|
||||||
@options[i] = params[i] if params[i]
|
|
||||||
}
|
|
||||||
@options['label'] ||= @name if @name != 'node'
|
|
||||||
end
|
|
||||||
|
|
||||||
def each_option
|
|
||||||
@options.each{ |i| yield i }
|
|
||||||
end
|
|
||||||
|
|
||||||
def each_option_pair
|
|
||||||
@options.each_pair{ |key, val| yield key, val }
|
|
||||||
end
|
|
||||||
|
|
||||||
#def parent=( thing )
|
|
||||||
# @parent.delete( self ) if defined?( @parent ) and @parent
|
|
||||||
# @parent = thing
|
|
||||||
#end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# this is used when we build nodes that have shape=record
|
|
||||||
# ports don't have options :)
|
|
||||||
class DOTPort < DOTSimpleElement
|
|
||||||
attr_accessor :label
|
|
||||||
|
|
||||||
def initialize( params = {} )
|
|
||||||
super( params )
|
|
||||||
@name = params['label'] ? params['label'] : ''
|
|
||||||
end
|
|
||||||
def to_s
|
|
||||||
( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# node element
|
|
||||||
class DOTNode < DOTElement
|
|
||||||
|
|
||||||
def initialize( params = {}, option_list = NODE_OPTS )
|
|
||||||
super( params, option_list )
|
|
||||||
@ports = params['ports'] ? params['ports'] : []
|
|
||||||
end
|
|
||||||
|
|
||||||
def each_port
|
|
||||||
@ports.each{ |i| yield i }
|
|
||||||
end
|
|
||||||
|
|
||||||
def << ( thing )
|
|
||||||
@ports << thing
|
|
||||||
end
|
|
||||||
|
|
||||||
def push ( thing )
|
|
||||||
@ports.push( thing )
|
|
||||||
end
|
|
||||||
|
|
||||||
def pop
|
|
||||||
@ports.pop
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s( t = '' )
|
|
||||||
|
|
||||||
label = @options['shape'] != 'record' && @ports.length == 0 ?
|
|
||||||
@options['label'] ?
|
|
||||||
t + $tab + "label = \"#{@options['label']}\"\n" :
|
|
||||||
'' :
|
|
||||||
t + $tab + 'label = "' + " \\\n" +
|
|
||||||
t + $tab2 + "#{@options['label']}| \\\n" +
|
|
||||||
@ports.collect{ |i|
|
|
||||||
t + $tab2 + i.to_s
|
|
||||||
}.join( "| \\\n" ) + " \\\n" +
|
|
||||||
t + $tab + '"' + "\n"
|
|
||||||
|
|
||||||
t + "#{@name} [\n" +
|
|
||||||
@options.to_a.collect{ |i|
|
|
||||||
i[1] && i[0] != 'label' ?
|
|
||||||
t + $tab + "#{i[0]} = #{i[1]}" : nil
|
|
||||||
}.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
|
|
||||||
label +
|
|
||||||
t + "]\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# subgraph element is the same to graph, but has another header in dot
|
|
||||||
# notation
|
|
||||||
class DOTSubgraph < DOTElement
|
|
||||||
|
|
||||||
def initialize( params = {}, option_list = GRAPH_OPTS )
|
|
||||||
super( params, option_list )
|
|
||||||
@nodes = params['nodes'] ? params['nodes'] : []
|
|
||||||
@dot_string = 'subgraph'
|
|
||||||
end
|
|
||||||
|
|
||||||
def each_node
|
|
||||||
@nodes.each{ |i| yield i }
|
|
||||||
end
|
|
||||||
|
|
||||||
def << ( thing )
|
|
||||||
@nodes << thing
|
|
||||||
end
|
|
||||||
|
|
||||||
def push( thing )
|
|
||||||
@nodes.push( thing )
|
|
||||||
end
|
|
||||||
|
|
||||||
def pop
|
|
||||||
@nodes.pop
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s( t = '' )
|
|
||||||
hdr = t + "#{@dot_string} #{@name} {\n"
|
|
||||||
|
|
||||||
options = @options.to_a.collect{ |name, val|
|
|
||||||
val && name != 'label' ?
|
|
||||||
t + $tab + "#{name} = #{val}" :
|
|
||||||
name ? t + $tab + "#{name} = \"#{val}\"" : nil
|
|
||||||
}.compact.join( "\n" ) + "\n"
|
|
||||||
|
|
||||||
nodes = @nodes.collect{ |i|
|
|
||||||
i.to_s( t + $tab )
|
|
||||||
}.join( "\n" ) + "\n"
|
|
||||||
hdr + options + nodes + t + "}\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# this is graph
|
|
||||||
class DOTDigraph < DOTSubgraph
|
|
||||||
def initialize( params = {}, option_list = GRAPH_OPTS )
|
|
||||||
super( params, option_list )
|
|
||||||
@dot_string = 'digraph'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# this is edge
|
|
||||||
class DOTEdge < DOTElement
|
|
||||||
attr_accessor :from, :to
|
|
||||||
def initialize( params = {}, option_list = EDGE_OPTS )
|
|
||||||
super( params, option_list )
|
|
||||||
@from = params['from'] ? params['from'] : nil
|
|
||||||
@to = params['to'] ? params['to'] : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s( t = '' )
|
|
||||||
t + "#{@from} -> #{to} [\n" +
|
|
||||||
@options.to_a.collect{ |i|
|
|
||||||
i[1] && i[0] != 'label' ?
|
|
||||||
t + $tab + "#{i[0]} = #{i[1]}" :
|
|
||||||
i[1] ? t + $tab + "#{i[0]} = \"#{i[1]}\"" : nil
|
|
||||||
}.compact.join( "\n" ) + "\n" + t + "]\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user