1#!/usr/bin/wish
2
3# Utility to create scanned synthesis matrices
4# John ffitch 2000 Jun 3
5
6# The basic drawing area.  Size is a guess!
7canvas .c -width 13c -height 13c
8pack .c
9
10#Creation of nodes and lines; driven my bindings later
11proc mkNode {x y} {
12    # Create new node at (x,y)
13    global nodeX nodeY edgeFirst edgeSecond allNodes
14    set new [.c creat oval [expr $x-5] [expr $y-5] \
15            [expr $x+5] [expr $y+5] -outline black \
16            -fill yellow -tags node]
17    set nodeX($new) $x
18    set nodeY($new) $y
19    set edgeFirst($new) {}
20    set edgeSecond($new) {}
21    lappend allNodes $new
22}
23
24proc mkEdge {first second} {
25                                # Create edge between nodes
26    global nodeX nodeY edgeFirst edgeSecond connect
27    set x1 $nodeX($first)
28    set y1 $nodeY($first)
29    set x2 $nodeX($second)
30    set y2 $nodeY($second)
31    set edge [.c create line $x1 $y1 $x2 $y2 -arrow last -arrowshape {10 20 5}]
32    .c lower $edge
33    lappend edgeFirst($first) $edge
34    lappend edgeSecond($second) $edge
35    lappend connect [list $first $second]
36}
37
38##########  LEFT BUTTON CREATION
39# Create node with left button
40bind .c <Button-1> {mkNode %x %y}
41
42.c bind node <Any-Enter> {
43    .c itemconfigure current -fill red
44}
45.c bind node <Any-Leave> {
46    .c itemconfigure current -fill yellow
47}
48
49#########  FIRST EDGE DRAWING METHOD
50# Line drawing with 1 and 2 -- must be a better way!
51
52set secondNode ""
53set firstNode ""
54bind .c 1 {
55    global firstNode secondNode
56    set firstNode [.c find withtag current]
57    if {($firstNode != "") && ($secondNode != "")} {
58        mkEdge $firstNode $secondNode
59        set firstNode ""
60        set secondNode ""
61    }
62}
63
64bind .c 2 {
65    global firstNode
66    set curNode [.c find withtag current]
67    if {($firstNode != "") && ($curNode != "")} {
68        mkEdge $firstNode $curNode
69        set firstNode ""
70    } else {
71        set secondNode $curNode
72    }
73}
74
75####### SECOND WAY
76# Second way of drawing links using Button 2
77bind .c <Button-2> {
78    global newLine curX curY
79    set firstNode [.c find withtag current]
80    if {$firstNode != ""} {
81        set newLine [.c create line %x %y %x %y -fill blue]
82        set curX %x
83        set curY %y
84    }
85}
86
87bind .c <B2-Motion> {
88    global newLine curX curY
89    .c coords $newLine [lindex [.c coords $newLine] 0] \
90                [lindex [.c coords $newLine] 1] %x %y
91    set curX %x
92    set curY %y
93    foreach node $allNodes {
94        set pts [.c coords $node]
95        set diffx [expr $curX-[lindex $pts 0]]
96        set diffy [expr $curY-[lindex $pts 1]]
97        if {($diffx < 10) && ($diffx > 0) && ($diffy < 10) && ($diffy > 0)} {
98            set curNode $node
99        }
100    }
101    if {($firstNode != "") && ($curNode != "") && ($firstNode != $curNode)} {
102        mkEdge $firstNode $curNode
103        set firstNode ""
104        .c delete $newLine
105        set newLine ""
106    }
107}
108
109bind .c <ButtonRelease-2> {
110                                # Delete any dangling rubber line
111    if {$newLine != ""} {
112        .c delete $newLine
113        set newLine ""
114    }
115}
116
117####### REORGANISATION OF LAYOUT
118# Node mobility, with attached lines
119proc moveNode {node xDist yDist} {
120    global nodeX nodeY edgeFirst edgeSecond
121    .c move $node $xDist $yDist
122    incr nodeX($node) $xDist
123    incr nodeY($node) $yDist
124    foreach edge $edgeFirst($node) {
125        .c coords $edge $nodeX($node) $nodeY($node) \
126                [lindex [.c coords $edge] 2] \
127                [lindex [.c coords $edge] 3]
128    }
129    foreach edge $edgeSecond($node) {
130        .c coords $edge [lindex [.c coords $edge] 0] \
131                [lindex [.c coords $edge] 1] \
132                $nodeX($node) $nodeY($node)
133    }
134}
135
136.c bind node <Button-3> {
137    set curX %x
138    set curY %y
139}
140
141.c bind node <B3-Motion> {
142    moveNode [.c find withtag current] [expr %x-$curX] [expr %y-$curY]
143    set curX %x
144    set curY %y
145}
146
147######## DELETIONS OF ERRORS
148#Removal of unwanted nodes
149proc deleteNode {node} {
150    global allNodes edgeFirst edgeSecond connect
151    if {[info exists $edgeFirst($node)]} {
152        foreach edge $edgeFirst($node) {
153            .c delete $edge
154        }
155    }
156    if {[info exists $edgeSecond($node)]} {
157        foreach edge $edgeSecond($node) {
158            .c delete $edge
159        }
160    }
161    unset edgeFirst($node)
162    unset edgeSecond($node)
163    set indx [lsearch $allNodes $node]
164    set allNodes [lreplace $allNodes $indx $indx]
165    while {[set indx [lsearch -regexp $connect "$node \[0-9\]*"]] != -1} {
166        set connect [lreplace $connect $indx $indx]
167    }
168    while {[set indx [lsearch -regexp $connect "\[0-9\]* $node"]] != -1} {
169        set connect [lreplace $connect $indx $indx]
170    }
171    .c delete $node
172}
173
174bind .c r {
175    deleteNode [.c find withtag current]
176}
177
178bind .c k {
179    deleteNode [.c find withtag current]
180}
181
182# Removal of unwanted lines
183proc deleteLink {node} {
184    global edgeFirst edgeSecond connect mode
185    if {[info exists $edgeFirst($node)]} {
186        bind .c y {
187            unset edgeFirst($node)
188            while {[set indx [lsearch -regexp $connect "$node \[0-9\]*"]] != -1} {
189                set connect [lreplace $connect $indx $indx]
190            }
191            .c delete $mode
192            set mode -1
193        }
194        bind .c n {
195            set mode -1
196            .c itemconfigure mode -fill black -outline black
197        }
198        foreach edge $edgeFirst($node) {
199            .c itemconfigure edge -fill yellow -outline yellow -stipple -.
200            set mode $edge
201            tkwait variable mode
202        }
203    }
204    if {[info exists $edgeSecond($node)]} {
205        bind .c y {
206            .c delete $mode
207            unset edgeSecond($node)
208            while {[set indx [lsearch -regexp $connect "\[0-9\]* $node"]] != -1} {
209                set connect [lreplace $connect $indx $indx]
210            }
211        }
212        bind .c n {
213            set mode -1
214            .c itemconfigure mode -fill black -outline black
215        }
216        foreach edge $edgeSecond($node) {
217            .c itemconfigure edge -fill yellow -outline yellow -stipple -.
218            set mode $edge
219            tkwait variable mode
220        }
221    }
222    bind .c y {}
223    bind .c n {}
224}
225
226bind .c d {
227    set node [.c find withtag current]
228    if {$node != ""} {
229        deleteLink $node
230    }
231}
232
233focus .c
234
235###### GENERATE OUTPUT TABLE
236set connect ""
237set allNodes ""
238set outname "matrix.dat"
239
240proc makeTable {} {
241                                # Construct the matrix
242    global allNodes connect outname
243    set n 0
244    set map ""
245#    puts "allNodes=$allNodes"
246#    puts "connections $connect"
247    foreach node $allNodes {
248                                # Construct a set of link tables
249#        puts "Node $n"
250        set links($n) ""
251        while {[set indx [lsearch -regexp $connect "$node \[0-9\]*"]] != -1} {
252#            puts "Indx = $indx; lindex connect indx = [lindex $connect $indx]"
253            set links($n) [lappend links($n) [lindex [lindex $connect $indx] 1]]
254            set connect [lreplace $connect $indx $indx]
255        }
256#        puts "Links $n $links($n)"
257#        puts $connect
258        set map [lappend map $node]
259#        puts "map for $n is $map"
260        set n [incr n 1]
261    }
262    set l 1
263    while {$l < $n} {
264        set l [expr $l+$l]
265    }
266    puts "*********************Table size is $l"
267    set ff [open $outname w]
268                                        # l is power-of-two version
269    for {set i 0} {$i < $l} {incr i 1} {
270        for {set j 0} {$j < $l} {incr j 1} {
271            if {($i<$n) || ($j<$n)} {
272                set k [lindex $map $j]
273                if {([lsearch $links($i) $k] != -1)} {
274                    puts -nonewline $ff "1 "
275                } else {
276                    puts -nonewline $ff "0 "
277                }
278            } else { puts -nonewline $ff "0 " }
279        }
280        puts $ff ""
281    }
282    puts "Ends"
283}
284
285button .ok -text Build -command makeTable
286button .xit -text EXIT -command exit
287set hlpShowing 0
288proc doHelp {} {
289    if {helpShowing==0} {
290        toplevel .hlp
291        wm title .hlp "Help"
292        text .hlp.t -relief raised -bd 2 -yscrollcommand ".hlp.s set"
293        scrollbar .hlp.s -command ".hlp.t yview"
294        button .hlp.k -text OK -command endHelp
295        pack .hlp.s -side right -fill y
296        pack .hlp.t -side left
297        pack .hlp.k
298        set f [open "matrix.hlp"]
299        while {![eof $f]} {
300            .hlp.t insert end [read $f 1000]
301        }
302        close $f
303        set helpShowing 1
304    }
305}
306
307proc endHelp {} {
308    destroy .hlp
309}
310
311button .help -text Help -command doHelp
312label .label -text "File Name:"
313entry .entry -width 20 -relief sunken -bd 2 -textvariable outname
314pack .xit .ok .help .label .entry -side left -padx 1m -pady 2m
315