]>
git.zerfleddert.de Git - micropolis/blob - src/tk/library/menu.tcl
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.
7 # $Header: /user6/ouster/wish/scripts/RCS/menu.tcl,v 1.11 92/08/08 14:49:55 ouster Exp $ SPRITE (Berkeley)
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.
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.
29 proc tk_menus
{w args
} {
33 if [catch {set result
[set tk_priv
(menusFor
$w)]}] {
40 catch {unset tk_priv
(menusFor
$w)}
44 set tk_priv
(menusFor
$w) $args
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.
52 proc tk_bindForTraversal args
{
54 bind $w <Alt-KeyPress
> {tk_traverseToMenu
%W
%A
}
55 bind $w <F10
> {tk_firstMenu
%W
}
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.
65 global tk_priv tk_strictMotif
66 if {[lindex [$w config
-state] 4] == "disabled"} {
69 set cur
$tk_priv(posted
)
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
80 set tk_priv
(posted
) $w
81 if {$tk_priv(focus) == ""} {
82 set tk_priv
(focus) [focus]
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]
88 $menu config
-activebackground [lindex [$menu config
-background] 4]
89 $menu config
-activeforeground [lindex [$menu config
-foreground] 4]
94 # The procedure below does all the work of unposting the menubutton that's
95 # currently posted. It takes no arguments.
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
107 set menu [lindex [$tk_priv(posted
) config
-menu] 4]
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
) {}
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
126 proc tk_traverseToMenu
{w char
} {
131 set char
[string tolower
$char]
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} {
139 [lindex [$mb config
-menu] 4] activate
0
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.
152 proc tk_traverseWithinMenu
{w char
} {
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]]}] {
164 if {[string compare
$char [string tolower
$char2]] == 0} {
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.
177 proc tk_getMenuButtons w
{
179 set top
[winfo toplevel $w]
180 if [catch {set buttons
[set tk_priv
(menusFor
$top)]}] {
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.
191 proc tk_nextMenu count
{
193 if {$tk_priv(posted
) == ""} {
196 set buttons
[tk_getMenuButtons
$tk_priv(posted
)]
197 set length
[llength $buttons]
198 for {set i
0} 1 {incr i
} {
202 if {[lindex $buttons $i] == $tk_priv(posted
)} {
211 while {$i >= $length} {
214 set mb
[lindex $buttons $i]
215 if {[lindex [$mb configure
-state] 4] != "disabled"} {
222 [lindex [$mb config
-menu] 4] activate
0
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.
230 proc tk_nextMenuEntry count
{
232 if {$tk_priv(posted
) == ""} {
235 set menu [lindex [$tk_priv(posted
) config
-menu] 4]
236 set length
[expr [$menu index last
]+1]
237 set i
[$menu index active
]
247 while {$i >= $length} {
250 if {[catch {$menu entryconfigure
$i -state} state
] == 0} {
251 if {[lindex $state 4] != "disabled"} {
260 # The procedure below invokes the active entry in the posted menu,
261 # if there is one. Otherwise it does nothing.
263 proc tk_invokeMenu
{menu} {
264 set i
[$menu index active
]
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
276 proc tk_firstMenu w
{
277 set mb
[lindex [tk_getMenuButtons
$w] 0]
280 [lindex [$mb config
-menu] 4] activate
0
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.
291 proc tk_mbButtonDown w
{
293 if {[lindex [$w config
-state] 4] == "disabled"} {
296 if {$tk_priv(inMenuButton
) == $w} {
299 set menu [lindex [$tk_priv(posted
) config
-menu] 4]
300 if {$tk_priv(window
) != $menu} {