## 8.3 Menubars

keyboard accelerators

A menubar is a frame widget containing several menubutton widgets. To each of the menubutton widgets a menu is attached. The menu contains menuitems being either radiobutton entries, checkbutton entries, command entries (similar to button widgets), separator entries or cascade entries to which sub menus are attached. The menu entries can be equipped with keyboard accelerators describing key event bindings that can be used to invoke the action of the menu entry. A keyboard accelerator must be added to the menu entry and the right event binding needs to be created.

Creating a menubar by hand has to follow this structure and is inconvenient due to the large numbers of different kinds of widgets and menu entries that are to be created. To ease the creation of a menubar, the `TkTools` module provides the procedure `TkTools.menubar` that creates to a given specification a menubar and creates keyboard accelerators with the right event bindings. The specification of a menubar consists of messages used to initialize the necessary widgets and entries, where the label determines the kind of entry to be created.

Figure 8.3 shows an example for menubar creation. The procedure `TkTools.menubar` takes two widgets and two menubar specifications as input and returns a frame containing the widgets for the menubar. The widget given as first argument serves as parent for the menubar's frame, whereas the widget given as second argument receives the key bindings for the accelerators. The specification given as third (fourth) argument describe the left (right) part of the menubar.

  `V={New Tk.variable tkInit(0)}
  B={TkTools.menubar W W
  [menubutton(text:'Test' underline:0
  menu: [command(label: 'About test'
  action: Browse#about
  key: alt(a)
  feature: about)
  separator
  command(label: 'Quit'
  action: W#tkClose
  key: ctrl(c)
  feature: quit)]
  feature: test)
  menubutton(text:'Options' underline:0
  menu: [checkbutton(label: 'Incremental'
  var: {New Tk.variable tkInit(false)})
  separator
  cascade(label: 'Size'
  menu: [radiobutton(label:'Small'
  var:V value:0)
  radiobutton(label:'Middle'
  var:V value:1)
  radiobutton(label:'Large'
  var:V value: 2)])])]
  nil}
  F={New Tk.frame tkInit(parent:W width:10#c height:5#c bg:ivory)}
  {Tk.send pack(B F fill:x)}`

Figure 8.3: A menubar.

A menubar specification consists of a list of `menubutton` messages. The valid options are those for the `tkInit` method of a menubutton widget object, where the parent field is not necessary, and the additional options `menu` and `feature`. The value for the `menu` option must be a list of specifications for the menu entries. The menu entries are specified similar to the menubuttons, the allow for the additional options `feature`, `key`, and `event`.

The value for the `key` describes the keyboard accelerator and event binding to be created. They can be used as follows:

`key` option value | accelerator | event binding
--- | --- | ---
`a` | a | `a`
`ctrl(a)` | C-a | `<Control-a>`
`alt(a)` | A-a | `<Alt-a>`
`alt(ctrl(a))` | A-C-a | `<Alt-Control-a>`
`ctrl(alt(a))` | C-A-a | `<Control-Alt-a>`

In case one wants to use different event bindings than those generated from the `key` option value, one can specify the event pattern as value for the option `event`.

The `feature` options for menubuttons and menu entries attach features to the created objects such that the object get accessible by these features. For instance, to disable the ``About test'' entry is possible with

  `{B.test.about tk(entryconfigure state:disabled)}`

The menus attached to menubuttons or to cascade entries can be accessed under the feature `menu`. For instance the first tear off entry from the ``Test'' menu can be removed with

  `{B.test.menu tk(configure tearoff:false)}`

It is possible to extend a menubar created with `TkTools.menubar` with further entries. The following statement adds a menu entry just before the `Quit` entry:

  `A={New Tk.menuentry.command tkInit(parent:B.test.menu
  before:B.test.quit
  label: 'Exit')}`

which can be deleted and removed from the menu again by:

  `{A tkClose}`