More about Menus

Create or Append? Menu vs. MenuItem?

X-Plane does some manipulation behind the scenes to make menu handling easy, but as with most magic, you might get confused if you try to figure out what is actually happening. Add to that the fact that, technically, all Python plugins appear to X-Plane as a single plugin (called XPPython3) additional manipulation is required in order to present to you, the python plugin developer, a consistent workable interface.

Plugins Menu

../_images/menu1.png

On start-up the “Plugins” menu contains a single item, “Show Plugin Admin”. This is added by Laminar and will display all loaded plugins. Note that because all python plugins are executed by XPPython3, only XPPython3 is listed. FPS impact for XPPython3 is the sum impact of all python plugins (XPPython3 by itself adds negligable overhead).

Top-Level Menu

Plugins can append to this “Plugins” Menu, under the “Show Plugin Admin” item. The order of added items is simply determined by the order of calls – by any plugin – to any of the following:

xp.createMenu(..., parentMenu=None, …)
xp.appendMenuItem(menuID=xp.findPluginsMenu())
xp.appendMenuItemWithCommand(menuID=xp.findPluginsMenu())
xp.appendSeparator(menuID=xp.findPluginsMenu())

We’ll call these “top-level” menu items – items directly placed under the “Plugins” menu.

If plugins intermix calls, the items will be intermixed: there is no way to guarantee all items by the same plugin are next to each other. There is no way to change the order of items.

For this reason, it is recommended that, if order is important, have a single top-level item for your plugin, and place your other menu items as sub-items. (That is, as items on a second-level menu.)

../_images/menu2.png

In the graphic to the right, we cannot tell if:

  1. One plugin created 5 items and one separator; or

  2. One plugin created Item 1 and item 2 and another plugin created Item3, Item 4, the separator and Item 5; or

  3. One plugin created Item 1, a second plugin created Item 2, the first plugin then created Item 3, a third plugin created Item 4, then the first plugin added the separator and Item 5.

Do you care?

../_images/menu3.png

You might, if you created multiple top-level items, and don’t make it clear to the user. For example, assume you have two plugins and one creates three items: “About”, “Reset”, separator, and “Quit” and the second plugin creates “About” and “Quit”. You might end up with something like the image on the right.

Don’t do that.

Converting MenuItems to Menus

We know you can add a menu to the bottom of the main Plugins menu by specifying None as the parent:

xp.createMenu('My Menu', None, 0, self.callback, self.menuRefCon)

Since it’s the plugin menu, can you specify xp.findPluginsMenu(), aren’t they the same?:

xp.createMenu('My Menu', xp.findPluginsMenu(), 0, self.callback, self.menuRefCon)

No.

If you specify a parent menu, then the menu and item must already exist. So in the former example, parentMenu is specified as None, so a new item is appended to the Plugins Menu (recall the parentItem=0 is ignored). In the latter example, the parentMenu is specified as whatever xp.findPluginsMenu() evaluates to, and the parentItem is used to determine which item to change.

And that’s the key: If you already have a menu item specified, you can convert it to a menu by using createMenu with the correct parent and correct menu item index.