Version 6 of Click me

Updated 2008-01-17 21:03:37 by nem

Richard Suchenwirth 2003-02-18 - Reading a Java tutorial in a bored moment, I came upon the ClickMe example at http://java.sun.com/docs/books/tutorial/java/concepts/practical.html (2007-10-03: dead link), where with only two Java class files, in less than 40 LOC, you can implement a rectangle where a red spot appears when you click on it. After compilation, you have 5 files (one HTML) that perform this feat.

Hm, thought I, how would that look in Tcl?


 package require Tk
 proc drawSpot {w x y r} {
    $w delete spot
    $w create oval [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]\
        -fill red -outline red -tag spot
 }
 pack [canvas .c]
 .c create rect 5 5 205 205 -fill white -outline black -tag box
 .c bind box <1> {drawSpot %W %x %y 7}

In order to reduce the ugly heap of expr calls, setok proposed this variation, with "specialist" functions for addition and subtraction:

 package require Tk
 proc + {x y} {expr {$x + $y}}
 proc - {x y} {expr {$x - $y}}
 proc drawSpot {w x y r} {
    $w delete spot
    $w create oval [- $x $r] [- $y $r] [+ $x $r] [+ $y $r]\
        -fill red -outline red -tag spot
 }
 pack [canvas .c]
 .c create rect 5 5 305 155 -fill white -outline black -tag box
 .c bind box <1> {drawSpot %W %x %y 7}

another variation without ugly expr calls:

 package require Tk
 interp alias {} = {} expr
 proc drawSpot {w x y r} {
    $w delete spot
    $w create oval [= $x-$r] [= $y-$r] [= $x+$r] [= $y+$r]\
      -fill red -outline red -tag spot
 }
 pack [canvas .c]
 .c create rect 5 5 305 155 -fill white -outline black -tag box
 .c bind box <1> {drawSpot %W %x %y 7}

(expr argument not in {...}, thus slower, but harmless here. Refer also to expr shorthand for Tcl9 -- RJM)

-- CN 03/10/2007: here's a variation with an expr that uses the tcl::mathfunc stuff that comes with 8.5:

 package require Tk 8.5
 proc tcl::mathfunc::drawSpot {w x1 y1 x2 y2} {
    $w delete spot 
    $w create oval $x1 $y1 $x2 $y2 -fill red -outline red -tag spot
 }
 pack [canvas .c]
 .c create rect 5 5 205 205 -fill white -outline black -tag box
 .c bind box <1> {expr {drawSpot("%W",%x-7,%y-7,%x+7,%y+7)}}

NEM 2008-01-17 offers this variant:

proc func {name params body} { proc $name $params [regsub -all {\(([^\)]*)\)} $body {[expr {\1}]}] }
func drawSpot {w x y r} { $w coords spot ($x-$r) ($y-$r) ($x+$r) ($y+$r) }
pack [canvas .c] -fill both -expand 1
.c create rect 5 5 205 205 -fill white -outline black -tags box
.c create oval 0 0 0 0 -fill red -outline red -tags spot
.c bind box <1> {drawSpot %W %x %y 7}

Arts and crafts of Tcl-Tk programming