Rubies:
This illustrates a bug in GraphViz, but it's otherwise useful as the
core of a tree-style user interface. It uses
Here's RGL:
http://www.rubygarden.org/ruby?RubyAlgorithmPackage/Graph
Here's GraphViz:
http://www.graphviz.org/
# put a GraphViz graph into a TkCanvas, and make nodes
# selectable. Illustrates a bug in GraphViz
require 'rgl/graphxml'
require 'rgl/adjacency'
require 'rgl/dot'
require 'tk'
include RGL
filename = ARGV[0]
puts 'Displaying ' + filename
# ruby canvas.rb examples/north/g.10.8.graphml &
# ruby canvas.rb examples/north/g.12.8.graphml &
# ruby canvas.rb examples/north/g.14.9.graphml &
File.open(filename) { |file|
graph = DirectedAdjacencyGraph.from_graphxml(file)
graph.write_to_graphic_file('gif', filename)
graph.write_to_graphic_file('plain', filename)
root = TkRoot.new{title "Ex1"}
canvas = TkCanvas.new(root) {
width 400
height 600
}
canvas.pack()
ovals = []
TkcImage.new(canvas, 0, 0) {
anchor 'nw'
image TkPhotoImage.new() {
file filename + '.gif'
}
}
# read the 'plain' file, and for each node put an invisible
# oval over its image
File.open(filename + '.plain') { |f|
graphLine = f.readline()
graphStats = graphLine.split()
graphHeight = graphStats[3].to_f()
nodeLine = f.readline()
fields = nodeLine.split()
while fields[0] == 'node'
namer = fields[1]
# the following crud is because GraphViz has no system to
# emit a "plain" format in pixels that exactly match the
# locations of objects in dot's raster output
# furtherless, the current GraphViz seems to be centering
# the raster output but not the 'plain' output. Hence on
# g.10.8.graphml the X fudge factor must be 45. >sigh<
# YMMV, based on your system's opinion of the size of an inch
exx = fields[2].to_f * 96 - 20 # 45
why = (graphHeight - fields[3].to_f()) * 96 - 20
widt = fields[4].to_f() * 90
hite = fields[5].to_f() * 90
ov = TkcOval.new(canvas, exx, why,
exx + widt, why + hite) {
state 'hidden'
width 4
outline 'green'
tags namer
}
ovals.push(ov)
nodeLine = f.readline()
fields = nodeLine.split()
end
}
lastOval = ovals[0]
# at click time, search for an oval in range and display it
canvas.bind('Button-1') do |event|
x,y = canvas.canvasx(event.x), canvas.canvasy(event.y)
ovals.each { |r|
x1,y1,x2,y2 = r.coords()
if x >= x1 and x <= x2 and y >= y1 and y <= y2 then
lastOval.configure('state' => 'hidden')
lastOval = r
lastOval.configure('state' => 'normal')
break
end
}
end
Tk.mainloop
}
--
Phlip