Annotation of micropolis/src/tk/library/menu.tcl, revision 1.1.1.1

1.1       root        1: # menu.tcl --
                      2: #
                      3: # This file contains Tcl procedures used to manage Tk menus and
                      4: # menubuttons.  Most of the code here is dedicated to support for
                      5: # menu traversal via the keyboard.
                      6: #
                      7: # $Header: /user6/ouster/wish/scripts/RCS/menu.tcl,v 1.11 92/08/08 14:49:55 ouster Exp $ SPRITE (Berkeley)
                      8: #
                      9: # Copyright 1992 Regents of the University of California
                     10: # Permission to use, copy, modify, and distribute this
                     11: # software and its documentation for any purpose and without
                     12: # fee is hereby granted, provided that this copyright
                     13: # notice appears in all copies.  The University of California
                     14: # makes no representations about the suitability of this
                     15: # software for any purpose.  It is provided "as is" without
                     16: # express or implied warranty.
                     17: #
                     18: 
                     19: # The procedure below is publically available.  It is used to indicate
                     20: # the menus associated with a particular top-level window, for purposes
                     21: # of keyboard menu traversal.  Its first argument is the path name of
                     22: # a top-level window, and any additional arguments are the path names of
                     23: # the menu buttons associated with that top-level window, in the order
                     24: # they should be traversed.  If no menu buttons are named, the procedure
                     25: # returns the current list of menus for w.  If a single empty string is
                     26: # supplied, then the menu list for w is cancelled.  Otherwise, tk_menus
                     27: # sets the menu list for w to the menu buttons.
                     28: 
                     29: proc tk_menus {w args} {
                     30:     global tk_priv
                     31: 
                     32:     if {$args == ""} {
                     33:        if [catch {set result [set tk_priv(menusFor$w)]}] {
                     34:            return ""
                     35:        }
                     36:        return $result
                     37:     }
                     38: 
                     39:     if {$args == "{}"} {
                     40:        catch {unset tk_priv(menusFor$w)}
                     41:        return ""
                     42:     }
                     43: 
                     44:     set tk_priv(menusFor$w) $args
                     45: }
                     46: 
                     47: # The procedure below is publically available.  It takes any number of
                     48: # arguments taht are names of widgets or classes.  It sets up bindings
                     49: # for the widgets or classes so that keyboard menu traversal is possible
                     50: # when the input focus is in those widgets or classes.
                     51: 
                     52: proc tk_bindForTraversal args {
                     53:     foreach w $args {
                     54:        bind $w <Alt-KeyPress> {tk_traverseToMenu %W %A}
                     55:        bind $w <F10> {tk_firstMenu %W}
                     56:     }
                     57: }
                     58: 
                     59: # The procedure below does all of the work of posting a menu (including
                     60: # unposting any other menu that might currently be posted).  The "w"
                     61: # argument is the name of the menubutton for the menu to be posted.
                     62: # Note:  if $w is disabled then the procedure does nothing.
                     63: 
                     64: proc tk_mbPost {w} {
                     65:     global tk_priv tk_strictMotif
                     66:     if {[lindex [$w config -state] 4] == "disabled"} {
                     67:        return
                     68:     }
                     69:     set cur $tk_priv(posted)
                     70:     if {$cur == $w} {
                     71:        return
                     72:     }
                     73:     if {$cur != ""} tk_mbUnpost
                     74:     set tk_priv(relief) [lindex [$w config -relief] 4]
                     75:     $w config -relief raised
                     76:     set tk_priv(cursor) [lindex [$w config -cursor] 4]
                     77:     $w config -cursor arrow
                     78:     $w post
                     79:     grab -global $w
                     80:     set tk_priv(posted) $w
                     81:     if {$tk_priv(focus) == ""} {
                     82:        set tk_priv(focus) [focus]
                     83:     }
                     84:     set menu [lindex [$w config -menu] 4]
                     85:     set tk_priv(activeBg) [lindex [$menu config -activebackground] 4]
                     86:     set tk_priv(activeFg) [lindex [$menu config -activeforeground] 4]
                     87:     if $tk_strictMotif {
                     88:        $menu config -activebackground [lindex [$menu config -background] 4]
                     89:        $menu config -activeforeground [lindex [$menu config -foreground] 4]
                     90:     }
                     91:     focus $menu
                     92: }
                     93: 
                     94: # The procedure below does all the work of unposting the menubutton that's
                     95: # currently posted.  It takes no arguments.
                     96: 
                     97: proc tk_mbUnpost {} {
                     98:     global tk_priv
                     99:     if {$tk_priv(posted) != ""} {
                    100:        $tk_priv(posted) config -relief $tk_priv(relief)
                    101:        $tk_priv(posted) config -cursor $tk_priv(cursor)
                    102:        $tk_priv(posted) config -activebackground $tk_priv(activeBg)
                    103:        $tk_priv(posted) config -activeforeground $tk_priv(activeFg)
                    104:        $tk_priv(posted) unpost
                    105: # deh multi display bug fix
                    106: #      grab none
                    107:        set menu [lindex [$tk_priv(posted) config -menu] 4]
                    108:        grab -off $menu
                    109:        focus $tk_priv(focus)
                    110:        set tk_priv(focus) ""
                    111:        $menu config -activebackground $tk_priv(activeBg)
                    112:        $menu config -activeforeground $tk_priv(activeFg)
                    113:        set tk_priv(posted) {}
                    114:     }
                    115: }
                    116: 
                    117: # The procedure below is invoked to implement keyboard traversal to
                    118: # a menu button.  It takes two arguments:  the name of a window where
                    119: # a keystroke originated, and the ascii character that was typed.
                    120: # This procedure finds a menu bar by looking upward for a top-level
                    121: # window, then looking for a window underneath that named "menu".
                    122: # Then it searches through all the subwindows of "menu" for a menubutton
                    123: # with an underlined character matching char.  If one is found, it
                    124: # posts that menu.
                    125: 
                    126: proc tk_traverseToMenu {w char} {
                    127:     global tk_priv
                    128:     if {$char == ""} {
                    129:        return
                    130:     }
                    131:     set char [string tolower $char]
                    132: 
                    133:     foreach mb [tk_getMenuButtons $w] {
                    134:        if {[winfo class $mb] == "Menubutton"} {
                    135:            set char2 [string index [lindex [$mb config -text] 4] \
                    136:                    [lindex [$mb config -underline] 4]]
                    137:            if {[string compare $char [string tolower $char2]] == 0} {
                    138:                tk_mbPost $mb
                    139:                [lindex [$mb config -menu] 4] activate 0
                    140:                return
                    141:            }
                    142:        }
                    143:     }
                    144: }
                    145: 
                    146: # The procedure below is used to implement keyboard traversal within
                    147: # the posted menu.  It takes two arguments:  the name of the menu to
                    148: # be traversed within, and an ASCII character.  It searches for an
                    149: # entry in the menu that has that character underlined.  If such an
                    150: # entry is found, it is invoked and the menu is unposted.
                    151: 
                    152: proc tk_traverseWithinMenu {w char} {
                    153:     if {$char == ""} {
                    154:        return
                    155:     }
                    156:     set char [string tolower $char]
                    157:     set last [$w index last]
                    158:     for {set i 0} {$i <= $last} {incr i} {
                    159:        if [catch {set char2 [string index \
                    160:                [lindex [$w entryconfig $i -label] 4] \
                    161:                [lindex [$w entryconfig $i -underline] 4]]}] {
                    162:            continue
                    163:        }
                    164:        if {[string compare $char [string tolower $char2]] == 0} {
                    165:            tk_mbUnpost
                    166:            $w invoke $i
                    167:            return
                    168:        }
                    169:     }
                    170: }
                    171: 
                    172: # The procedure below takes a single argument, which is the name of
                    173: # a window.  It returns a list containing path names for all of the
                    174: # menu buttons associated with that window's top-level window, or an
                    175: # empty list if there are none.
                    176: 
                    177: proc tk_getMenuButtons w {
                    178:     global tk_priv
                    179:     set top [winfo toplevel $w]
                    180:     if [catch {set buttons [set tk_priv(menusFor$top)]}] {
                    181:        return ""
                    182:     }
                    183:     return $buttons
                    184: }
                    185: 
                    186: # The procedure below is used to traverse to the next or previous
                    187: # menu in a menu bar.  It takes one argument, which is a count of
                    188: # how many menu buttons forward or backward (if negative) to move.
                    189: # If there is no posted menu then this procedure has no effect.
                    190: 
                    191: proc tk_nextMenu count {
                    192:     global tk_priv
                    193:     if {$tk_priv(posted) == ""} {
                    194:        return
                    195:     }
                    196:     set buttons [tk_getMenuButtons $tk_priv(posted)]
                    197:     set length [llength $buttons]
                    198:     for {set i 0} 1 {incr i} {
                    199:        if {$i >= $length} {
                    200:            return
                    201:        }
                    202:        if {[lindex $buttons $i] == $tk_priv(posted)} {
                    203:            break
                    204:        }
                    205:     }
                    206:     incr i $count
                    207:     while 1 {
                    208:        while {$i < 0} {
                    209:            incr i $length
                    210:        }
                    211:        while {$i >= $length} {
                    212:            incr i -$length
                    213:        }
                    214:        set mb [lindex $buttons $i]
                    215:        if {[lindex [$mb configure -state] 4] != "disabled"} {
                    216:            break
                    217:        }
                    218:        incr i $count
                    219:     }
                    220:     tk_mbUnpost
                    221:     tk_mbPost $mb
                    222:     [lindex [$mb config -menu] 4] activate 0
                    223: }
                    224: 
                    225: # The procedure below is used to traverse to the next or previous entry
                    226: # in the posted menu.  It takes one argument, which is 1 to go to the
                    227: # next entry or -1 to go to the previous entry.  Disabled entries are
                    228: # skipped in this process.
                    229: 
                    230: proc tk_nextMenuEntry count {
                    231:     global tk_priv
                    232:     if {$tk_priv(posted) == ""} {
                    233:        return
                    234:     }
                    235:     set menu [lindex [$tk_priv(posted) config -menu] 4]
                    236:     set length [expr [$menu index last]+1]
                    237:     set i [$menu index active]
                    238:     if {$i == "none"} {
                    239:        set i 0
                    240:     } else {
                    241:        incr i $count
                    242:     }
                    243:     while 1 {
                    244:        while {$i < 0} {
                    245:            incr i $length
                    246:        }
                    247:        while {$i >= $length} {
                    248:            incr i -$length
                    249:        }
                    250:        if {[catch {$menu entryconfigure $i -state} state] == 0} {
                    251:            if {[lindex $state 4] != "disabled"} {
                    252:                break
                    253:            }
                    254:        }
                    255:        incr i $count
                    256:     }
                    257:     $menu activate $i
                    258: }
                    259: 
                    260: # The procedure below invokes the active entry in the posted menu,
                    261: # if there is one.  Otherwise it does nothing.
                    262: 
                    263: proc tk_invokeMenu {menu} {
                    264:     set i [$menu index active]
                    265:     if {$i != "none"} {
                    266:        tk_mbUnpost
                    267:        update idletasks
                    268:        $menu invoke $i
                    269:     }
                    270: }
                    271: 
                    272: # The procedure below is invoked to keyboard-traverse to the first
                    273: # menu for a given source window.  The source window is passed as
                    274: # parameter.
                    275: 
                    276: proc tk_firstMenu w {
                    277:     set mb [lindex [tk_getMenuButtons $w] 0]
                    278:     if {$mb != ""} {
                    279:        tk_mbPost $mb
                    280:        [lindex [$mb config -menu] 4] activate 0
                    281:     }
                    282: }
                    283: 
                    284: # The procedure below is invoked when a button-1-down event is
                    285: # received by a menu button.  If the mouse is in the menu button
                    286: # then it posts the button's menu.  If the mouse isn't in the
                    287: # button's menu, then it deactivates any active entry in the menu.
                    288: # Remember, event-sharing can cause this procedure to be invoked
                    289: # for two different menu buttons on the same event.
                    290: 
                    291: proc tk_mbButtonDown w {
                    292:     global tk_priv
                    293:     if {[lindex [$w config -state] 4] == "disabled"} {
                    294:        return
                    295:     } 
                    296:     if {$tk_priv(inMenuButton) == $w} {
                    297:        tk_mbPost $w
                    298:     }
                    299:     set menu [lindex [$tk_priv(posted) config -menu] 4]
                    300:     if {$tk_priv(window) != $menu} {
                    301:        $menu activate none
                    302:     }
                    303: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.