This page uses CSS, and renders properly in the latest versions of Microsoft Internet Explorer and Mozilla.
This is Frontier: The Definitive Guide by Matt Neuburg, unabridged and unaltered from the January 1998 printing.
It deals with the freeware Frontier 4.2.3; for commercial Frontier 8, look here, and for the inexpensive Radio UserLand, look here. See my Web site for information.
Those wishing an offline or printed copy may purchase the book, which is still in print.
Copyright 1998 O'Reilly & Associates, Inc. ALL RIGHTS RESERVED. Reprinted with permission.
TOP UP: Interface NEXT: Agents and Hooks

26

Menus and Suites

This chapter describes Frontier's menus and explains how to edit them, manually and programmatically. The chapter also discusses the implementation of suites, miniature applications written in UserTalk and included in the database.

Among Frontier's menus, the File menu, the Edit menu, and the Window menu are intrinsic. They are hard-coded into the Frontier application; they cannot be altered. This chapter is not about them.

All other menus are custom menus. The remarkable thing about custom menus is that they are implemented in UserTalk, within the database. The menus themselves, as they appear at the top of the screen, are simply reflections of editable database objects called menubars. A menubar has an edit window, like a script or an outline. You can edit a menubar by hand; a menubar can also be changed through UserTalk. Edit a menubar, and you've changed the actual menu that appears at the top of the screen. Every item in a menubar has an attached script, which runs when the actual menu item is chosen at the top of the screen; edit the script, and you've changed what the menu item does.

alt
NOTE Because the term "menubar" refers in Frontier to an object datatype, I speak in this chapter of the computer's menubar (the place where menu names appear and from which menus pop down) as "the top of the screen." I speak of the menus and menu items that appear at the top of the screen as "actual" menus and menu items.
alt

Menu Categories

Frontier manages its custom menus in some unusual ways. It will help to divide Frontier custom menus into four categories:

Stable menus

These menus are always present. These have been rearranged somewhat over the history of Frontier; at present they consist of the Main menu, the Open menu, the Web menu, the =user.initials menu (its actual name matches the user.initials database entry), and the Suites menu.

Modal menus

One of these appears automatically, depending on what kind of window is frontmost: the Table menu, the Script menu, the Outline menu, the WP menu, and the Menubar menu.

Suite menus

A suite is a miniature application implemented in UserTalk, and each suite can include a menu, to provide a menu interface to its functionality. The available suite menus are listed in the Suites menu, and choosing from that menu will cause the named suite menu to appear.

Shared menus

These appear in certain other applications (such as BBEdit, Eudora, Internet Explorer, and others), even though they belong to Frontier. Frontier's functionality can be conveniently accessed from them without leaving the other application.

Modifying Menus

Being able to make a menu item at any time, with any desired script attached to it, means that frequently needed utility scripts can be run by choosing from a menu. It is convenient and easy to make a new menu item. This is one of Frontier's nicest features.

As with the database, though, so with menubars - you should be careful not to make wanton or accidental changes to menus that belong more to UserLand than to you. Clearly you ought not delete the Open menu, or alter a Main menu item's script so that it breaks or causes harm.

The =user.initials menu is the one that belongs completely to you; it is the chief place where you are permitted and expected to add menu items as desired. It is also reasonable to customize a shared menu by adding your own items to it, but future Frontier upgrades may overwrite your changes. If you write a suite, its suite menu is yours to define. Other menus should probably be considered off limits, unless you are very sure of what you are doing.

As with the rest of the database, you are encouraged to explore the menubars and the scripts of the menu items to learn how they work.

Where the Menubars Are

Menubars for the four types of custom menu reside at different locations in the database:

  • The stable menus are in a single object, system.misc.menubar.
  • The modal menus are in the table at suites.modes.menus.
  • The suite menus live each in its own suite in an object called menu; for instance, the Droplets menu, which appears when you choose Droplet Developer from the Suites menu, is at suites.droplet.menu.
  • The shared menus are in the table at system.menubars.

Menubar Edit Windows

A menubar is a non-scalar: it has an edit window, like a script or an outline. You can open that edit window as you would that of any other non-scalar - for example, by double-clicking the table entry for that object, or by selecting the entry and hitting Enter.

You can also open a menubar from the actual menu at the top of the screen. To do so, choose a menu item while holding the Option key; the edit window of the menubar opens, with that item selected. Some menus (suite menus, mostly) also have an Edit Menu item which, when chosen, opens the menubar for editing.

You can open system.misc.menubar by hitting the Menu Bar button in the Main Window, or by choosing Menu Editor from the Open menu.

Menubars as Outlines

A menubar edit window is a species of outline. Each line of an indented bundle represents a menu item; the line that the indented bundle is subordinate to represents the menu containing those items. Lines at summit level in a menubar represent actual menus in the computer's menubar at the top of the screen; other lines that have subheads represent hierarchical submenus.

alt
NOTE Although menubars are outlines, the lines they contain represent menus and menu items, so I shall refer to the lines of menubars as "items."
alt

Since a menubar is an outline, everything you already know about working with outlines applies. You can collapse and expand items, navigate, create, delete, reorganize, and edit items just as you do lines in an outline. The Menubar menu, which appears at the top of the screen when a menubar edit window is frontmost, is almost entirely a subset of the Outline menu.

Expanding and collapsing items in a menubar edit window has no effect on the look of the actual menu; it's just for convenience in editing. Similarly, you can change the text font and size of the menubar edit window, but this doesn't affect the actual menu.

Menubars and Actual Menus

While a menubar edit window is frontmost, the actual menu that it represents appears at the top of the screen (if it wasn't already showing). Changes that you make in the menubar edit window are reflected immediately in the actual menu, which you can drop down to see how it looks, or to choose an item and see how its script runs.

There are certain special coded correspondences between an item of a menubar and the actual menu item it represents:

  • To make an actual menu item be a separator line, have its item in the menubar consist of just a hyphen. (When you navigate out of the line, it will take on the look of a separator line even in the edit window.)
  • To make an actual menu item be checkmarked, have its item in the menubar start with an exclamation mark (!).
  • To make an actual menu item be disabled, have its item in the menubar start with a left parenthesis (( ).
  • To make the name of an actual menu item be calculated at the moment the actual menu is dropped down, have its item in the menubar start with an equal sign (=) and consist of a UserTalk expression.1 (Try making an item of a menubar read =clock.now( ) and then drop down the actual menu a few times!) If the name, checkmark, or enabled status of a menu item needs to change depending on present conditions, make the item a call to a script, and have the script return the correct name. To see an example, look at how the Enable Agents item of the Main menu works; it calls system.misc.agentsMenuItem() for its name.
  • A calculated menu name, as opposed to a menu item name, is calculated just once, when the actual menu is installed at the top of the screen; that's how the name of the =user.initials menu is generated.

Keyboard Shortcuts

Keyboard shortcuts let the user choose a menu item without dropping the menu down with the mouse. To assign a keyboard shortcut to a menu item, select its item in the menubar and choose Set Command Key from the popup menu at the edit window's lower left. When the dialog appears, type the key - not the actual shortcut. (So, to set a shortcut as Command-2, type 2.)

Only simple Command key shortcuts are available; you can't make a shortcut be Control-a or Command-Shift-T. No visible distinction is made between regular keyboard keys and keypad keys, but they are different. (So, for instance, the keyboard shortcut for Full Expand in the Outline menu is Command-keypad-*.) The popup menu shows a list of shortcuts already set for this menubar; choosing from it navigates to the chosen item.

With so many menus and such a limited range of shortcuts available, conflicts are inevitable. When the user hits a keyboard shortcut within Frontier, Frontier searches each menu at the top of the screen starting with the rightmost; it is the first matching menu item thus encountered that will be chosen. Conflicts caused by menus that appear only temporarily (especially suite menus) are not regarded as highly problematic.

In a shared menu, the host application searches the shared menu after its own menus, so a keyboard shortcut in a shared menu that matches the shortcut for one of the application's own menu items causes no problems for the application - but the shared menu item can't be chosen with a keyboard shortcut, either.

Menu Item Scripts

Every menu item has a script attached to it, which is executed when the actual menu item is chosen by the user. This script is accessible for editing only when the menubar is open for editing. In the menubar, select the item and hit the Script button (or Command-Enter). A script edit window opens. This window does not, itself, represent a database object; it is a feature of the menubar object. When a menubar edit window is closed, any open menu item script windows associated with it are closed as well.

You can associate a script with an item that is a separator line or a menu (as opposed to a menu item); but such a script cannot be run by way of the menu interface, because the actual menu item cannot be chosen by the user.

Menu item scripts have no eponymous handler; the script is associated with no script object, and has no name for a handler to be eponymous to. When an actual menu item is chosen, its script runs just as when the script edit window's Run button is pushed: top-level commands are executed.

Menu item script windows have no Compile button; they are compiled afresh whenever the script runs. (This poses no danger, because an agent or other "involuntary" mechanism is not going to run a menu item script while it is open for editing. See Chapter 13, Running and Debugging Scripts.) Menu item scripts can be tested "live": when you make a change, choosing the actual menu item runs the changed script without your having to close the script edit window.

Because they are not precompiled, menu item scripts should be fairly short, so as to compile and start executing rapidly when the actual menu item is chosen. Often, a menu item script will consist of a single line, which calls some script object in the database. This makes editing and maintenance easier, too, since a database script object is more convenient to access and debug than a menu item script.

Debugging a menu item script can be a little tricky. You can't just choose the actual menu item; you have to open the menu item's script and press the Debug button. But now conditions on the screen may not match those under which the script normally runs. Suppose, for instance, that choosing the menu item is supposed to operate upon the window that is frontmost. Let's say this is expected to be an outline edit window. If an outline was frontmost before you started debugging, it isn't frontmost now: there's a menubar window in front of it, and a menu item script edit window in front of that!

Now, the menu item script edit window itself doesn't really count; as we've already seen (Chapter 24, Windows), when you press Run or Debug in a script edit window, calls to a verb like window.frontmost() return a reference to the window behind it. However, we don't want the window behind it to be the menubar edit window. Closing the menubar edit window won't help; that will cause the menu item script edit window to close too! What I do is hide menubar edit windows just before debugging a menu item script, using the following utility.

Example 26-1 hideMbars( )
loop (local (w = window.frontmost()); w ≠ ""; w = window.next(w))
    if defined(w^)
        if typeOf(w^) == menuBarType
            window.hide(w)

Shared Menus

Shared menus are menus belonging to Frontier that appear in another application. That other application (the host application) cannot be simply any application; it has to have been deliberately coded in accordance with Frontier's menu-sharing protocol.2 But even applications that don't support menu sharing can be made to do so with an extension, OSA Menu, by Leonard Rosenthol.3 Frontier must be running for its shared menus to appear in other applications.

The shared menus mechanism works by way of the table at system.menubars . Each entry in this table is a menubar whose name is the creator code of that menubar's host application. So, for instance, system.menubars.["R*ch"] causes a Site menu to appear in BBEdit; system.menubars.CSOm causes a Scripts menu to appear in Eudora.

When the user chooses a shared menu item, its script runs, just as with any Frontier custom menu item. Typically, the purpose of the script will be to add functionality to the host application. This involves having Frontier drive the application; see Chapter 32, Driving Other Applications.

For example, in Eudora, choosing Uppercase from the Selected Text hierarchical submenu of the Scripts menu runs this script:

Eudora.replaceSelectedText (string.upper (Eudora.getSelectedText ()))

This makes up for the fact that Eudora has no facility for turning text to uppercase; Frontier does have such a facility. In Netscape Navigator, choosing Edit Local File from the Scripts menu drives a word processor to open the file one is viewing in the browser, so you can modify its HTML. This makes up for the fact that Netscape has no facility for telling an application to open a file; Frontier does have such a facility. The BBEdit Site menu provides tight integration with Frontier's Web site management facilities. See Chapter 41, Web Site Management.

The Mac OS Finder shared menu is implemented through OSA Menu, and provides a wide miscellany of utilities, including making an alias of the selected file , stuffing the selected file and attaching it to a new email message, backing up, reconciling two folders, changing a file's type and creator, sending a file to a specified application to open, and many others.

A special situation arises with regard to the Netscape Navigator and Microsoft Internet Explorer shared menus (MOSS and MSIE). UserLand can't know which browser you're going to use, but it wants their shared menus to have identical functionality. Therefore, an agent script (see Chapter 27, Agents and Hooks), system.agents.webBrowserAgent(), watches to see if the shared menus differ, and reconciles them if they do. This can have some surprising effects if you're unaware of it; if you find this troublesome, you can comment out the lines of the agent that do this.

Within a host application, choosing a shared menu item while holding the Option key brings Frontier to the front and opens the menubar for editing. This makes it easy to explore or modify the scripts behind the existing shared menus.

Special Considerations

Although Frontier runs the script when a shared menu item is chosen, the host application is hosting the process, so that scripts which run perfectly when initiated from within Frontier may behave differently when initiated from a shared menu. The following sections describe the chief differences.

Threads

When a shared menu item is chosen, the host application must contact Frontier. If Frontier then starts driving the host application, wires can get crossed: the host application may be waiting for Frontier's response to what it told Frontier to do, so it isn't listening to what Frontier is telling it to do. A symptom is that everything seems to freeze up for a while. That, for instance, is what happened with a shared menu item script I wrote for Netscape Navigator. The script said simply:

people.man.driveNavigator()

But the script at people.man.driveNavigator was starting out with a webBrowser.openURL() command, and Navigator wasn't ready to respond to this, so nothing was happening.

The solution is to spawn a thread. My problem went away when I changed the shared menu item script to that the following.

Example 26-2 Spawning a thread
evaluateThread("people.man.driveNavigator()")

The verb evaluateThread() is an old, undocumented verb that should do exactly the same thing as thread.evaluate() . There seems to be a mysterious bug involving thread.evaluate() in shared menus, so I don't try to call it there.

Sometimes, you just can't get a direct threading call to work. In such cases, there is a trick which I call "stepping out to Apple events." The idea is to build a script and send it to Frontier as a 'dosc' Apple event (see Chapter 34, Driving Frontier from Outside). You just have to be careful of quoted strings inside quoted strings. Here is one way to modify Example 26-2 so that it uses Apple events.

Example 26-3 Stepping out to Apple events
local (s)
s = "thread.evaluate(\"people.man.driveNavigator()\")"
misc.doScript('LAND', s)

If you don't want to use Apple events, you can use another method, which I call "agent polling."4 The shared menu item script puts a UserTalk expression into a preordained location in the database; that's all. Meanwhile, an agent script in Frontier is checking this location every second; if it finds anything there, it removes it (so it won't find it next time) and then spawns a thread to evaluate it. In my implementation, the agent script is at system.agents.watchDoThis, and is shown in Example 26-4.

Example 26-4 Agent polling
if people.man.doThis ≠ ""
    local (s = people.man.doThis)
    people.man.doThis = ""
    thread.evaluate(s)
clock.sleepFor (1)

Then the shared menu script would look like this:

people.man.doThis = "people.man.driveNavigator()"

It is possible to sophisticate the structure with semaphores, but you get the general idea.

Memory

Because the shared menu item script runs in the host application's context, there may not be enough memory to run it successfully. Sometimes you can solve the problem by increasing the host application's memory allocation, but the usual solution is to spawn a thread by one of the three methods just described. That way, the real work of the shared menu script is done in Frontier's context.

An example is at FinderMenu.commands.reconciler(), which is called by the Finder's shared menu item Reconcile Folders; the Finder hasn't enough memory to hold the operation, so the script calls toys.threadCall(), which in turn calls evaluateThread(), to do the real work.

Dialogs

If a script's execution was initiated by the user choosing from a shared menu, any Frontier dialogs put up during execution appear in the host application, not in Frontier. (Modeless dialogs run as modal, but at least they do appear.) Many shared menu scripts take advantage of this feature (see FinderMenu.commands. reconciler() again, for instance).

But now and then it isn't the desired behavior. Suppose, for instance, the script switches to Frontier, does something-or-other, and then puts up a dialog. That dialog will appear back in the host application; the user won't see it unless the script switches to the host application first.

Once again, a new thread can solve the problem, because it initiates a new context from within Frontier. If I call this script from a shared menu in Eudora:

frontier.bringtofront()
dialog.notify("howdy")

the dialog shows up in Eudora; but if I call this script instead:

frontier.bringtofront()
evaluateThread("dialog.notify(\"howdy\")")

the dialog shows up in Frontier.

alt
WARNING A dialog that is put up by a dialog.runModeless() call cannot be made to appear in a host application at all. The Find/Replace dialog is an example.
alt
Giving up

Shared menus can be touchy creatures. Sometimes the threading tricks shown earlier can help, but sometimes menu sharing just doesn't work. For instance, on my computer, choosing any shared menu item in Microsoft Internet Explorer will crash the computer.

Fortunately, there's very little inconvenience in switching to Frontier and running the script from there instead. Or, I can usually save the script to disk (see Chapter 29, Import/Export) and run it from OSA Menu's script menu, or I can save it as a desktop script and run it from the Apple menu. So menu sharing is neat, but there are alternatives.

Modal Menus

The various modal menus appear depending on the nature of the frontmost window; for example, if a table edit window is frontmost, the Table menu appears. The mechanism behind this is an agent script at system. agents.statusMessage, which is called every second. The first thing this agent does is to call suites.modes.monitor() , which gets the datatype of the object represented by the frontmost window and looks up that datatype in suites.modes.menus, substituting the menubar there for the current modal menu, if there is one. This script is worth studying; it is simple and clever.

If agents are disabled, the modal menu system will stop operating. As explained in Chapter 27, you can disable agents by choosing Disable Agents from the Main menu. You might need to disable agents if you thought one of them was causing a problem - if, for instance, you edited an agent and compiled it, only to discover you'd made some serious mistake. Just be aware that you're also going to lose the modal menus and the functionality they contain.

Suites

A suite is a collection of scripts with related functionality - basically, a miniature application - stored in a subtable of the suites table, and accessed through a menu which appears when a certain item of the Suites menu is chosen.

Not every suite, though, meets this canonical description. The suites table has come to be a repository for all sorts of script collections. A suite need not have a menu specific to it, or if it does, it may not be a suite menu. For example, suites.applescripts contains the implementation for the three items of the Applescripts submenu of the Main menu; suites.html contains the implementation for the whole Web menu; suites.regex is the sort of thing you'd expect would live at system.extensions; suites.samples and suites.toys are just miscellaneous collections of unrelated scripts.

Accessing and Removing Suite Menus

A suite's menu doesn't appear until you summon it, which you do by choosing an item from the Suites menu, usually from its UserLand Suites submenu. For example, if you choose Object Database Map, the Map menu appears. If you choose NetFrontier, the NetFrontier menu appears. These are suite menus; the Suites menu is a menu for summoning suite menus.

Normally, only one suite menu is present at a time; if you summon a suite menu when a suite menu is already present, the old one goes away. To remove any suite menus, choose Minimal Menus from the Suites menu.

Writing a Suite

A set of scripts is a candidate for packaging as a suite if it forms a unified functionality that one needs only occasionally. But the usual reason for making a suite has to do with distribution. A suite can be packaged as a single exported file and distributed to other Frontier users; when a user imports a suite, the menu item in the Suites menu that summons its suite menu is automatically created. So a suite is a way of letting other users access your miniature Frontier-based application.

If you have a collection of scripts that you think would make a good suite, choose Make New Suite from the Suites menu. This calls suites.samples.basicStuff.createNewSuite() , a brilliant script which is worthy of study. You should try making a new suite even if you don't intend to do anything with it, just to see what it's like.

When you choose Make New Suite, a dialog box requests a title for the suite. This title will be used for, among other things, the name of your suites subtable, and changing this later will break things, so choose the title carefully.

Let's say you call your suite toot. What you now have is a framework for your toot suite. A suites.toot subtable is created, containing four items: a wptext called readMe, into which to place instructions for the user; your suite's menubar, called menu; and two scripts, installMenu and importSuite. You will add scripts and other objects to suites.toot as desired, to implement the functionality of your suite.

Your toot suite menu, in suites.toot.menu, initially contains three items: Read Me, Edit Menu, and Edit Table. Feel free to change the menu name toot, and to add menu items (and even other menus) to the menubar as needed to access the functionality of the scripts you'll put into suites.toot.

A new menu item in the Suites menu, called toot, summons your suite menu. It calls menu.addSuite(), which in turn calls suites.toot.installMenu(). toot.installMenu() calls menu.install() to put your suite menu at the top of the screen; you can modify it so that it also performs other tasks. For example, the tableMap suite has an extra line in its installMenu() script that calls tableMap.zoomer() to open the tableMap.list outline.5

If you're going to distribute your suite, toot.importSuite() becomes important. It is called, once and once only, when a user imports your suite into the database. It puts into the user's Suites menu the toot menu item that summons your suite menu; this is done by calling menu.importSuite() . The second parameter in the call to menu.importSuite() is the name of the menu item that will go into the Suites menu, so if you don't like the name toot for that menu item, toot.importSuite() is the place to change it.

Your importSuite() script is also your chance to prepare the database (kindly and carefully!) as may be required by your suite. For an example, study suites.classAds.importSuite(). It calls an init() script to create and initialize a dozen or so objects in the database, and a folder on the disk. These are all things that the suite will need in order to do its work later on. Typically, if a suite needs private ancillary objects in the database, the user table is the proper place to create them.

Clearly the onus is on the programmer to plan and test before distributing any suite. One should write only to acceptable places in the database, and be certain to do no damage. In my own copy of the database, I have disabled the automatic call to importSuite() when a suite is imported; I don't like the idea of running a script from another user before I've had a chance to study it. See Chapter 29.

Programmatic Menu Manipulation

Menubar items are strings, so matches on them are case-sensitive.

To add an item to a menubar:

menu.addMenuCommand (addrMenubar, menuName, itemName, scriptString)

scriptString is a string, but what's to be made from it is a menu item script. The way this works is that scriptString becomes the first and only line of the script; if the script is to consist of more than one command, it can be notated using semicolons and curly braces, but the new menu item script will still consist of only one line. Here, for example, I add to my =user.initials menu a menu item that beeps 10 times slowly.

Example 26-5 Making a menu item
local (s)
s = "for x = 1 to 10 {"
s = s + "speaker.beep();"
s = s + "clock.waitseconds(1);}"
menu.addmenucommand (@system.misc.menubar, "=user.initials", "BeepALot", s)

It is possible to use a different technique and edit the menu item script as an outline; an example appears later in this section.

The new item goes at the end of its menu. If that isn't where you wanted to put it, the menubar can be edited as an outline using the op verbs to move the item after it is created. This too is illustrated later.

To insert a copy of an existing menubar into another menubar:

menu.addSubMenu (addrDestMenubar, menuName, addrSourceMenubar)

To delete a menu item:

menu.deleteMenuCommand (addrMenubar, menuName, itemName)
menu.deleteSubMenu (addrMenubar, menuName)

The difference is that deleteMenuCommand() lets you specify the item more precisely, and won't delete an item with subheads.

There is a certain element of danger to these verbs: menu.addSubMenu() and menu.deleteSubmenu(), especially, can replace or remove, respectively, a menu containing many items.

In actuality, menu.addMenuCommand(), menu.addSubMenu(), and menu.deleteSubMenu() do not distinguish between menus and menu items in the menubar they are altering: they simply look, scanning from top to bottom, for any item whose text matches menuName.

To open a menu item script edit window:

menu.zoomscript ()

To copy between a menu item script and a script object:

menu.getScript (addrScriptObject)
menu.setScript (addrScriptObject)

The three verbs menu.zoomscript(), menu.getScript() and menu.set-Script() do not specify a menubar or item because the item must already be selected in a menubar edit window which is already the "target." For more about the target, see Chapter 18, Non-Scalars.

Also in Chapter 18 are described the verbs that let you edit a script or menubar as an outline (the op verbs). These are needed for more sophisticated actions upon menu item scripts and menubars than the menu verbs permit. As an illustration, we modify Example 26-5 so as to place BeepALot first in the =user.initials menu and so that its script consists of three lines.

Example 26-6 Making a menu item, moving it, and editing its script
local (s); new(scriptType, @s)
bundle «construct the script in a script object variable
    target.set(@s)
    op.setLinetext("for x = 1 to 10")
    op.insert("speaker.beep()", right)
    op.insert("clock.waitseconds(1)", down)
    target.clear()
menu.addmenucommand (@system.misc.menubar, "=user.initials", "BeepALot", "")
bundle «edit the menubar, move the new item up and attach the script
    target.set(@system.misc.menubar)
    while op.getLineText() ≠ "BeepALot"
        op.go(flatdown,1)
    op.reorg(up, infinity)
    menu.setscript(@s)
    target.clear()

There are also several verbs that control which custom menus appear at the top of the screen.

To remove all custom menus from the top of the screen:

menu.clearMenubar ()

To restore the default custom menus at the top of the screen, with no suite menus:

menu.noSuite ()

To add a menubar to the top of the screen:

menu.install (addrMenubar)

To remove a menubar from the top of the screen:

menu.remove (addrMenubar)

To learn whether a menubar is present at the top of the screen:

menu.isInstalled (addrMenubar)

To add or remove a menubar at the top of the screen:

menu.toggle (addrMenubar)

To remove all suite menus and call a suite's installMenu():

menu.addSuite (addrSuiteTable)

These verbs are part of Frontier's internal menu management, and would probably be called by your scripts only if you were taking over menu management yourself. You might, for instance, want to turn Frontier into a specialized application in which only your custom menus appear.


1. Don't do this in the Finder's shared menu; there's a bug that can cause a crash.

2. This is described in the Frontier SDK, which includes header and code files for inclusion in a project, plus a model application illustrating when and how to make function calls so as to support menu sharing.

3. For the latest version of OSA Menu, see http://www.lazerware.com/~leonardr/.

4. The idea for this comes from Cameron Smith.

5. Similarly, you can define a closeSuite() script that will be called when your suite menu is removed by choosing Minimal Menus (or calling menu.noSuite()); unfortunately, it is not called when your suite menu is replaced by another, so it's not as useful as it might be.


TOP UP: Interface NEXT: Agents and Hooks

This is Frontier: The Definitive Guide by Matt Neuburg, unabridged and unaltered from the January 1998 printing.
It deals with the freeware Frontier 4.2.3; for commercial Frontier 8, look here, and for the inexpensive Radio UserLand, look here. See my Web site for information.
Those wishing an offline or printed copy may purchase the book, which is still in print.
Copyright 1998 O'Reilly & Associates, Inc. ALL RIGHTS RESERVED. Reprinted with permission.