links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
Extending the menu
Last updated at 8:21 am UTC on 4 April 2017
Copied from Mailing List – Thu, Sep 3, 2015 at 12:41 AM, Subj: The Trunk: Monticello-eem.617.mcz

Proposal for discussion

How to allow packages to extend the menus

We can talk this over when we meet in Palo Alto, but the idea is an important one, and I'm paying for having been too lazy to write it up properly. Let me try and give a quick sketch here.

The goals are to

- if menus are created every time a user invokes a menu, then to simply include the relevant extensions in the menu
- if menus are stored in variables, to automatically construct, or reconstruct the menu when either loading or unloading of a package changes the items in a menu

We design menu pragmas in action methods to specify


With this specification a package can extend any number of menus in tools simply by being loaded, with no collisions with any other packages defining extensions on those menus. Tools become freely pluggable, and system configurations constructed from different sets of loaded packages are decoupled; we don't need many menu definitions, just an initial base menu which is extended with the current set of extensions.

For this to work we need to "name" menus, and to use some numbering scheme to define groups (menu entries between lines) and elements within each group. One simple scheme is to use numbers:

So given

MenuMorph fromArray: {
{'find...(f)' translated.	#find}.
{'find again (g)' translated.	#findAgain}.
{'set search string (h)' translated.	#setSearchString}.
{'do again (j)' translated.	#again}.
{'undo (z)' translated.	#undo}.
{'copy (c)' translated.	#copySelection}.
{'cut (x)' translated.	#cut}.
{'paste (v)' translated.	#paste}.
{'paste...' translated.	#pasteRecent}.
{'set font... (k)' translated.	#offerFontMenu}.
{'set style... (K)' translated.	#changeStyle}.
{'set alignment...' translated.	#chooseAlignment}.
{'more...' translated.	#shiftedTextPaneMenuRequest}.

you could imagine the following numberings:

    10.01    find
    10.02    findAgain
    10.03    setSearchString
    20.01    again
    20.02    undo
    30.01    copySelection
    30.02    cut
    30.03    paste
    30.04    pasteRecent
    40.01    offerFontMenu
    40.02    changeStyle
    40.03    chooseAlignment

So I can specify e.g. a new group inserted before the first one by using, e.g. 5.005 as an index, and can slot an item between again and undo using 20.015, etc.

This gives us menu pragmas that look like:

TextEditor methodsFor: 'SpellChecker-extensions' stamp: 'mad hacker 9/9/1999'
    <menuAction: #yellowButtonMenu
      label: 'spell check selection (s)'
      position: 10.035>
    ...code implementing spell checking...

(note that the action, #spellCheck, is implicit, it is the selector of the method containing the pragma)

- if menus are created every time a user invokes a menu, then search for pragmas within the relevant class hierarchy, compute, sort and insert individual extensions to the menu
- if menus are stored in variables, to have compilation and method removal send a message to the class to/from which method(s) are added/removed so that the class can recompute menus (as in the line above) when code is added/removed.

What I saw in ChangeSorter was quite different. It seems to be a way of specifying entire menus, and I'm not sure how these menus are to be combined. Maybe I'm misunderstanding the way the scheme is supposed to work. What I've described above is very close to the one that pragmas came from in the first place, which was my attempt to decouple the components that could be loaded into VisualWorks when we decomposed the system into easily loadable parcels. Up until that point VisualWorks had had all its tool menus predefined, disabling items that were to do with components delivered as file-ins that weren't yet filed-in. It was too rigid. It didn't allow for future expansion. And so I had the idea of menu pragmas to decouple things. Steve Dahl then came up with the scheme to define a base menu, number its items appropriately, and extend the menu.

One of the things that's really nice about the VisualWorks scheme is that the menu pragma itself is actually implemented (remember that pragmas are Message instances with literal parameters). The class MenuBuilder (IIRC) implemented various menu pragma methods so the patten is

So one can find other menu pragmas using senders, and find the editor using implementors, and one can extend the scheme by adding additional methods to MenuEditor, again possibly loaded from packages.

HTH, Eliot

See also
Popup Menus