home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / incoming / jstools-.6v3 / jstools- / jstools-tk3.6v3.0 / lib / joptionbutton.tcl < prev    next >
Encoding:
Text File  |  1995-02-05  |  5.6 KB  |  225 lines

  1. # joptionbutton.tcl - one-of-many choice button with popup list
  2. # Copyright 1994 by Jay Sekora.  All rights reserved, except 
  3. # that this file may be freely redistributed in whole or in part 
  4. # for non-profit, noncommercial use.
  5. ######################################################################
  6.  
  7. ######################################################################
  8. # create a new option button.  -font and -width can adjust appearance.
  9. #   -list is not really optional.  -current can set current value.
  10. ######################################################################
  11.  
  12. proc j:option { w args } {
  13.   j:parse_args {
  14.     {font {}}
  15.     {list {(none)}}
  16.     {width 20}
  17.     {current {}}
  18.   }
  19.   # should do error checking on args.
  20.   
  21.   global LIST_FOR_$w
  22.   global OPTION_FOR_$w
  23.   
  24.   if {"x$current" == "x"} {
  25.     set current [lindex $list 0]
  26.   }
  27.   set OPTION_FOR_$w $current
  28.   
  29.   set LIST_FOR_$w $list
  30.   
  31.   # parameterise following:
  32.   label $w -width $width -textvariable OPTION_FOR_$w \
  33.     -borderwidth 2 -relief raised
  34.   if [string length $font] {
  35.     $w configure -font $font
  36.   }
  37.   
  38.   frame $w.bump -height 6 -width 10 -borderwidth 2 -relief raised
  39.   place $w.bump -in $w -relx 0.95 -rely 0.5 -anchor e
  40.   
  41.   bind $w <ButtonPress-1> [list \
  42.     j:option:popup .option_popup $w \
  43.   ]
  44.   
  45.   catch {rename ${w}-orig {}}
  46.   rename $w ${w}-orig
  47.   proc $w { option args } [format {
  48.     set tmp %s
  49.     global OPTION_FOR_$tmp
  50.     
  51.     switch -exact $option {
  52.       get {
  53.         return [set OPTION_FOR_$tmp]
  54.       }
  55.       set {
  56.         return [set OPTION_FOR_$tmp [lindex $args 0]]
  57.       }
  58.       configure {
  59.         return [j:option:configure $tmp $args]
  60.       }
  61.       default {
  62.         error "Invalid argument $option to option widget command $tmp."
  63.       }
  64.     }
  65.   } $w]
  66. }
  67.  
  68. ######################################################################
  69. # configure a setting for an optionbutton widget.
  70. #   this should be more general, and it should be used by initial
  71. #   arg-parsing code for j:option .
  72. ######################################################################
  73.  
  74. proc j:option:configure { w arglist } {
  75.   upvar #0 OPTION_FOR_$w current_value
  76.   upvar #0 LIST_FOR_$w current_list
  77.   
  78.   if {[llength $arglist] == 1} {
  79.     set option [lindex $arglist 0]
  80.     switch -exact -- $option {
  81.       -font {
  82.         return [${w}-orig configure -font]
  83.       }
  84.       -list {
  85.         return [list -list list List {(none)} $current_list]
  86.       }
  87.       -current {
  88.         return [list -current current Current {} $current_value]
  89.       }
  90.       -width {
  91.         return [${w}-orig configure -width]
  92.       }
  93.       default {
  94.         error "unknown option \"$option\""
  95.       }
  96.     }
  97.   }
  98.   
  99.   while {[llength $arglist] > 0} {
  100.     set option [lindex $arglist 0]
  101.     set value [lindex $arglist 1]
  102.     if {"x$value" == "x"} {
  103.       error "no value given to option \"$option\"."
  104.     }
  105.     
  106.     set arglist [lreplace $arglist 0 1]    ;# with nothing
  107.     
  108.     switch -exact -- $option {
  109.       -font {
  110.         ${w}-orig configure -font $value
  111.       }
  112.       -list {
  113.         set current_list $value
  114.       }
  115.       -current {
  116.         set current_value $value
  117.       }
  118.       -width {
  119.         ${w}-orig configure -width $value
  120.       }
  121.       default {
  122.         error "unknown option \"$option\""
  123.       }
  124.     }
  125.   }
  126. }
  127.  
  128. ######################################################################
  129. # create (and position properly) the popup list invoked by <1>
  130. ######################################################################
  131.  
  132. proc j:option:popup { w button } {
  133.   upvar #0 OPTION_FOR_$button value
  134.   upvar #0 LIST_FOR_$button list
  135.   
  136.   # make sure the current value is in the list:
  137.   if {[lsearch -exact $list $value] == -1} {
  138.     set list [linsert $list 0 $value]
  139.   }
  140.   
  141.   toplevel $w
  142.   wm transient $w [winfo toplevel $button]
  143.   wm overrideredirect $w 1
  144.   wm withdraw $w
  145.   
  146.   set width [lindex [$button configure -width] 4]
  147.   set font [lindex [$button configure -font] 4]
  148.   
  149.   listbox $w.lb \
  150.     -font $font \
  151.     -exportselection 0 \
  152.     -borderwidth 2 -relief raised -cursor arrow
  153.   
  154.   j:tk3 {$w.lb configure -geometry ${width}x[llength $list]}
  155.   j:tk4 {
  156.     $w.lb configure -width $width -height [llength $list]
  157.     $w.lb configure -highlightthickness 0
  158.   }
  159.   pack $w.lb -in $w
  160.     
  161.   foreach item $list {
  162.     $w.lb insert end $item
  163.   }
  164.   
  165.   # guess positioning of listbox so current value is over button:
  166.   
  167.   # get pixels per line - toplevel size is in pixels
  168.   update
  169.   set lines [llength $list]
  170.   set pixels [winfo reqheight $w]
  171.   set pixels_per_line [expr $pixels / $lines]
  172.   
  173.   # index is position of current value in list;
  174.   # offset is that times pixels per line:
  175.   set index [lsearch -exact $list $value]
  176.   set offset [expr $index * $pixels_per_line]
  177.  
  178.   # subtract offset (position of current in list) from button y position:
  179.   set x [winfo rootx $button]
  180.   set y [expr [winfo rooty $button] - $offset]
  181.   
  182.   wm geometry $w +$x+$y
  183.   wm deiconify $w
  184.   
  185.   # disable all current bindings:
  186.   foreach event [bind Listbox] {
  187.     bind $w.lb $event {}
  188.   }
  189.   
  190.   j:tk3 {
  191.     bind $w.lb <Visibility> "
  192.       grab -global %W
  193.       %W select from $index
  194.       %W select to $index
  195.     "
  196.   }
  197.   j:tk4 {
  198.     bind $w.lb <Visibility> "
  199.       grab -global %W
  200.       %W selection clear 0 end
  201.       %W selection set $index $index
  202.     "
  203.   }
  204.   
  205.   bind $w.lb <Any-ButtonRelease-1> "
  206.     set OPTION_FOR_$button \[%W get \[%W nearest %y\]\]
  207.     grab release %W
  208.     destroy \[winfo toplevel %W\]
  209.   "
  210.   
  211.   j:tk3 {
  212.     bind $w.lb <Any-B1-Motion> {
  213.       %W select from [%W nearest %y]
  214.       %W select to [%W nearest %y]
  215.     }
  216.   }
  217.   j:tk4 {
  218.     bind $w.lb <Any-B1-Motion> {
  219.       %W selection clear 0 end
  220.       %W selection set [%W nearest %y] [%W nearest %y]
  221.     }
  222.   }
  223. }
  224.