vector.tk

This is a further development of the Space Game. First I wrote the procedures in tcl, and got them past the "very rough" stage. Then I put them into a Tk script.

Well, I tried to, anyway. For the longest time I could not get the thing to work, because I did not understand how to make a label change after the widget was packed and presented. However, I flipped through Clif Flynt's book BOOK Tcl/Tk for Real Programmers and found an example that showed it could be done. I just needed to figure out how to do it.

This is round two of coding. The best thing I did was start fresh, and delete everything. Well, I kept the "quit" button.....


 #!/bin/sh

 #\
 exec wish "$0" "${1+$@}"
 # EE: Explanation of previous line can be found in page [exec magic]

 # Are there ever any arguments to this?  :)
 # EE: Doesn't matter. better to have it there for future possibility.

 #### All the procedures up front
 # Proc to evaluate the coordinates given
 # Returns the list of coordinates
 # Input should be in the form of xxx,yyy,zzz
 # Split by commas, test for 3 variables, and test for non-numerics.
 # Then, and only then, return the list as valid.

 # Needs a Tk based error message instead of an "exit" if fails to
 # validate.  Done 2 jun 01.
 # Does it need quite the level of math precision?

 proc validateCoord { coord } {
    global goodVectors
    set coordName [ split $coord , ]
    if {([ llength $coordName ] != "3") || ([regexp {[^0-9 ]} \
 "$coordName"])} {
 # Okay, this was an early issue. If the user entered a bad datum
 # the program would die. No forgiveness
 #       exit
 # Change "exit" to:
   errorMsg $coord
   set goodVectors false
    }
    return $coordName
    }


 proc calcVector { hN tT } {
    # Add the "goodVectors" value
    global goodVectors
    # clear goodVectors if set earlier
    if { [ info exists goodVectors ] } {
        unset goodVectors
    }

    set hereCoord [ validateCoord $hN ]
    set thereCoord [ validateCoord $tT ]
   # This was added, it tests for the variable "goodVectors"
   # If it is set, that means there are problems, and it 
   # sets the output label to show an error. 
   # If the goodVectors is not set, then continue on. The problem
   # was that the math needed to be wrapped so that it did not 
   # try to compute if the information was bad.
   # Does that make sense?  :)
    if { [ info exists goodVectors ] } {
        set distance "error-please redo"
    } else {

    foreach x1 $hereCoord x2 $thereCoord {
    lappend vector [expr {$x2 - $x1}]
    }

    foreach {X Y Z} $vector  break
    set distance [expr {hypot($X, hypot($Y,$Z))}]
 
    return "${X},${Y},${Z} @ $distance "

    }
 }

 # This whole proc was added to give better error messaging
 # than a program crash. :)

 proc errorMsg { badInfo } {
 #   If they blow it, wake them up!
    bell

 #   This is a failed try to handle 2 sets of exactly similar
 #   bad input.
 #   if { [ info exists errLabel ] } {
 #       set badInfo ${badInfo}2
 #   }

    set errLabel $badInfo
 #   The ".ack$badInfo covers if the user inputs a blank
    toplevel .ack$badInfo

    message .ack${badInfo}.1 -text "Please use standard Galactic \
     format: xx,yy,zz. not $badInfo"
    
    wm title .ack${badInfo} "ERROR"
    pack .ack${badInfo}.1
 }




 #### Put up the UI
 # Quit      button
 button .quit -text "Quit" -command exit
 
 set hN [ entry .e1 -width 12 -textvariable input1 ]
 set tT [ entry .e2 -width 12 -textvariable input2 ]
 set out [ label .l1 -width 30 -textvariable output ]

 set action [ button .b1 -text "Get Vector" -command {\
        set output [ calcVector  $input1 $input2 ] } ]

 pack $hN $tT $out $action .quit -side left