1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
|
#!/bin/sh
# next line is a comment in tcl \
exec wish8.3 "$0" ${1+"$@"}
package require Tkspline
package require Tcldot
# Maria reachability graph visualizer
# by Marko Mkel (msmakela@tcs.hut.fi)
# based on the DotEd demo and feedback from John Ellson (ellson@lucent.com)
global saveFill tk_library g
# as the mouse moves over an object change its shading
proc mouse_anyenter {c} {
global tk_library saveFill
set item [string range [lindex [$c gettags current] 0] 1 end]
set saveFill [list $item [lindex [$c itemconfigure 1$item -fill] 4]]
$c itemconfigure 1$item -fill black \
-stipple @$tk_library/demos/images/gray25.bmp
}
# as the mouse moves out of an object restore its shading
proc mouse_anyleave {c} {
global saveFill
$c itemconfigure 1[lindex $saveFill 0] \
-fill [lindex $saveFill 1] -stipple {}
}
# if button is pressed over a node, perform a command on it
proc mouse_press {c x y cmd} {
global g
set x [$c canvasx $x]
set y [$c canvasy $y]
foreach item [$c find overlapping $x $y $x $y] {
foreach tag [$c gettags $item] {
if {[string first "node" $tag] == 1} {
set l [[string range $tag 1 end] showname]
puts "$cmd $l"
return
}
}
}
}
proc loadDirectory {w type} {
if {$type != ""} {set type .$type}
$w.d.entry delete 0 end
$w.d.entry insert end [pwd]
$w.d.l.list delete 0 end
if {[pwd] != "/"} {
$w.d.l.list insert end ".."
}
foreach i [lsort [glob -nocomplain *]] {
if {[file isdirectory $i]} {
$w.d.l.list insert end [file tail $i]
}
}
$w.f.l.list delete 0 end
foreach i [lsort [glob -nocomplain *$type]] {
if {! [file isdirectory $i]} {
$w.f.l.list insert end [file tail $i]
}
}
}
proc loadDirectory_list {w type x y} {
cd [$w.d.l.list get @$x,$y]
loadDirectory $w $type
}
proc loadDirectory_entry {w type} {
cd [$w.d.entry get]
loadDirectory $w $type
}
proc update_entry {w x y} {
$w.entry delete 0 end
$w.entry insert end [$w.l.list get @$x,$y]
}
proc positionWindow {w} {
set pos [split [wm geometry .] +]
set x [expr [lindex $pos 1] - 350]
set y [expr [lindex $pos 2] + 20]
wm geometry $w +$x+$y
}
proc saveFileByName {w name type} {
if {[file exists $name]} {
confirm "File exists. Shall I overwrite it?" \
"saveFileByNameDontAsk $w $name $type"
} {
saveFileByNameDontAsk $w $name $type
}
}
proc saveFileByNameDontAsk {w name type} {
global g
if {[catch {open $name w} f]} {
warning "Unable to open file for write:\n$name; return"
}
if {$type == "dot"} {
set type canon
}
$g write $f $type
close $f
if {$w != {}} {destroy $w}
message "Graph written to:\n$name"
}
proc saveFileByName_list {w x y type} {
set dirName [$w.d.entry get]
if {[catch {cd $dirName}]} {
warning "No such directory:\n$dirName; return"
}
if {$dirName == "/"} {set dirName ""}
saveFileByName $w $dirName/[$w.f.l.list get @$x,$y] $type
}
proc saveFileByName_entry {w type} {
set dirName [$w.d.entry get]
if {[catch {cd $dirName}]} {
warning "No such directory:\n$dirName; return"
}
if {$dirName == "/"} {set dirName ""}
saveFileByName $w $dirName/[$w.f.entry get] $type
}
proc saveFileAs {type} {
set w .save
catch {destroy $w}
toplevel $w
positionWindow $w
wm title $w "Save Dot File"
wm iconname $w "Save"
frame $w.d
label $w.d.label -text "Directory:"
frame $w.d.l
listbox $w.d.l.list -width 30 -height 10 -yscrollcommand "$w.d.l.scroll set"
bind $w.d.l.list <Double-1> "loadDirectory_list $w $type %x %y; break"
bind $w.d.l.list <1> "update_entry $w.d %x %y"
scrollbar $w.d.l.scroll -command "$w.d.l.list yview"
pack $w.d.l.list $w.d.l.scroll -side left -fill y -expand 1
frame $w.d.space1 -height 3m -width 20
entry $w.d.entry -width 30
frame $w.d.space2 -height 3m -width 20
button $w.d.cancel -text Cancel -command "destroy $w"
bind $w.d.entry <Return> "loadDirectory_entry $w $type"
pack $w.d.label $w.d.l $w.d.space1 $w.d.entry $w.d.space2 -side top -anchor w
pack $w.d.cancel -side top
frame $w.space -height 3m -width 3m
frame $w.f
label $w.f.label -text "File:"
frame $w.f.l
listbox $w.f.l.list -width 30 -height 10 -yscrollcommand "$w.f.l.scroll set"
bind $w.f.l.list <Double-1> "saveFileByName_list $w %x %y $type; break"
bind $w.f.l.list <1> "update_entry $w.f %x %y"
scrollbar $w.f.l.scroll -command "$w.f.l.list yview"
pack $w.f.l.list $w.f.l.scroll -side left -fill y -expand 1
frame $w.f.space1 -height 3m -width 20
entry $w.f.entry -width 30
frame $w.f.space2 -height 3m -width 20
button $w.f.load -text Save -command "saveFileByName_entry $w $type"
bind $w.f.entry <Return> "saveFileByName_entry $w $type; break"
pack $w.f.label $w.f.l $w.f.space1 $w.f.entry $w.f.space2 -side top -anchor w
pack $w.f.load -side top
pack $w.d $w.space $w.f -side left -fill y -expand true
loadDirectory $w $type
}
proc confirm {msg cmd} {
set w .confirm
catch {destroy $w}
toplevel $w
positionWindow $w
wm title $w "Confirm"
wm iconname $w "Confirm"
label $w.message -text "\n$msg\n"
frame $w.spacer -height 3m -width 20
frame $w.buttons
button $w.buttons.confirm -text OK -command "$cmd; destroy $w"
button $w.buttons.cancel -text Cancel -command "destroy $w"
pack $w.buttons.confirm $w.buttons.cancel -side left -expand 1
pack $w.message $w.spacer -side top -anchor w
pack $w.buttons -side bottom -expand y -fill x -pady 2m
}
proc message {m} {
set w .message
catch {destroy $w}
toplevel $w
positionWindow $w
wm title $w "Message"
wm iconname $w "Message"
label $w.message -text "\n$m\n"
pack $w.message -side top -anchor w
update
after 2000 "destroy $w"
}
proc warning {m} {
set w .warning
catch {destroy $w}
toplevel $w
positionWindow $w
wm title $w "Warning"
wm iconname $w "Warning"
label $w.message -text "\nWarning:\n\n$m"
pack $w.message -side top -anchor w
update
after 2000 "destroy $w"
}
# lay the graph out
proc layoutgraph {g c} {
$c delete all
$g layout
eval [$g render $c]
$c configure -scrollregion [$c bbox all]
}
proc parse {ch} {
global g c
set line [gets $ch]
if {[eof $ch]} { exit }
switch $line {
"new();" {
if {[catch {dotread $ch} g]} {
puts stderr "maria-vis: invalid graph"
} else {
layoutgraph $g $c
}
}
"add();" {
if {[catch {dotread $ch} g2]} {
puts stderr "maria-vis: invalid graph"
} else {
# merge the nodes
foreach i [$g2 listnodes] {
[$g addnode [$i showname]] setattributes \
[$i queryattributevalues [$i listattributes]]
}
# merge the edges
foreach i [$g2 listedges] {
foreach {t h} [$i listnodes] {break}
[$g addedge [$t showname] [$h showname]] setattributes \
[$i queryattributevalues [$i listattributes]]
}
layoutgraph $g $c
}
}
default { puts stderr "maria-vis: unrecognized cmd: $line" }
}
}
set saveFill {}
set g [dotnew digraph]
wm title . "Maria Browser"
wm iconname . "Maria"
wm minsize . 50 100
wm geometry . 400x300
frame .m -relief raised -borderwidth 1
frame .a
frame .b
set c [canvas .a.c -cursor crosshair \
-xscrollcommand ".b.h set" \
-yscrollcommand ".a.v set" \
-width 0 \
-height 0 \
-borderwidth 0]
bind $c <1> "mouse_press $c %x %y visual\\ visual\\ succ"
bind $c <2> "mouse_press $c %x %y visual\\ visual\\ pred"
$c bind all <Any-Enter> "mouse_anyenter $c"
$c bind all <Any-Leave> "mouse_anyleave $c"
scrollbar .b.h -orient horiz -relief sunken -command "$c xview"
scrollbar .a.v -relief sunken -command "$c yview"
menubutton .m.file -text "File" -underline 0 -menu .m.file.m
menu .m.file.m
.m.file.m add command -label "Save As ..." -underline 5 \
-command "saveFileAs dot"
.m.file.m add separator
.m.file.m add cascade -label "Export" -underline 1 \
-menu .m.file.m.export
menu .m.file.m.export
.m.file.m.export add command -label "PNG ..." -underline 0 \
-command "saveFileAs png"
.m.file.m.export add command -label "GIF ..." -underline 0 \
-command "saveFileAs gif"
.m.file.m.export add command -label "SVG ..." -underline 0 \
-command "saveFileAs svg"
.m.file.m.export add command -label "ISMAP ..." -underline 0 \
-command "saveFileAs ismap"
.m.file.m.export add command -label "HPGL ..." -underline 0 \
-command "saveFileAs hpgl"
.m.file.m.export add command -label "MIF ..." -underline 0 \
-command "saveFileAs mif"
.m.file.m.export add command -label "PCL ..." -underline 1 \
-command "saveFileAs pcl"
.m.file.m.export add command -label "PostScript ..." -underline 0 \
-command "saveFileAs ps"
.m.file.m add separator
.m.file.m add command -label "Exit" -underline 0 -command "exit"
pack append .m .m.file {left}
pack append .a $c {left expand fill} .a.v {right filly}
pack append .b .b.h {left expand fillx}
pack append . .m {top fillx} .a {expand fill} .b {bottom fillx}
tk_menuBar .m.file
fileevent stdin readable "parse stdin"
|