Version 0 of Analog Count Down Clock

Updated 2006-09-09 19:19:32

set ::secs_togo 0

 proc countdown_start { } {
   countdown_reset
   countdown_continue
 }

 proc countdown_continue { } {
   .c itemconfigure face -fill white
   draw_hands
   if !$::secs_togo {
     .start configure -text "Start" -command countdown_start
     .c itemconfigure face -fill green
     bell
     return
   }
   .start configure -text "Pause" -command countdown_pause
   incr ::secs_togo -1
   after 1000 countdown_continue
 }
 proc countdown_pause { } {
   catch {after cancel countdown_continue}
   .c itemconfigure face -fill blue
   .start configure -text "Continue" -command countdown_continue
 }
 proc countdown_reset { } {
   catch {after cancel countdown_continue}
   set ::secs_togo [expr $::seconds+60*$::minutes]
   .c itemconfigure face -fill $::bg
   .start configure -text "Start" -command countdown_start
   draw_hands
 }

 proc draw_hand { hand angle decorations } {
   set end_xy [get_xy $hand $angle]
   eval .c create line $::size $::size $end_xy $decorations
 }

 proc end_coordinate {hand difference} {
   set length [expr {$hand == "seconds" ? .9 : .8}]
   set hand_length [expr $::size * $length]
   return [expr $::size + $hand_length * $difference]
 }

 proc get_xy { hand angle } {
   return [list [end_coordinate $hand [expr sin($angle)]] \
                      [end_coordinate $hand [expr -cos($angle)]]]
 }

 proc draw_hands {} {
   set seconds $::secs_togo
   catch {.c delete withtag hands}
   set twopi 6.283185
   set seconds_angle [expr $seconds * $twopi / 60.]
   draw_hand seconds $seconds_angle "-width 1 -tags hands"
   set minutes_angle [expr $seconds_angle / 60.]
   draw_hand minutes $minutes_angle \
       "-width 2 -capstyle projecting -arrow last -tags hands"
 }

 proc init {} {
   catch {destroy .c}
   set ::size 30
   set full_diameter [expr 2 * $::size]

   canvas  .c -width $full_diameter -height $full_diameter
   button  .start -text "Start" -command countdown_start
   button  .reset -text "Reset" -command countdown_reset
   label   .l -text "mm:ss"
   spinbox .m -textvariable ::minutes -width 2 -justify right \
       -from 0 -to 59 -validate key -vcmd {expr "%P<0||%P>59?0:1"}
   spinbox .s -textvariable ::seconds -width 2 -justify right \
       -from 0 -to 59 -validate key -vcmd {expr "%P<0||%P>59?0:1"}

   set ::bg [.c cget -background]

   grid .l .m .s -sticky ew
   grid .c - -
   grid .start - .reset -sticky ew

   set border 2
   set diameter [expr 2 * $::size - $border]
   .c create oval $border $border $diameter $diameter \
       -fill $::bg -outline black -tag face
 }

 # Example usage:
 init