Skip to content

Latest commit

 

History

History
537 lines (391 loc) · 18.5 KB

menu.md

File metadata and controls

537 lines (391 loc) · 18.5 KB

The 'menu' namespace

The menu namespace provides os-independent functions for manipulating menu items. For Finale this is particularly useful in the Plug-Ins menu, since by default Finale places all the plugins in a flat menu structure. These functions allow a script (executing at startup) to rearrange the plugin menus into a more usable menu tree.

The Windows and macOS operating systems treat menus slightly differently. In macOS, the top-level menu is associated with the application, whereas in Windows any window can have a top-level menu. Finale for Windows runs in an MDI Client window, and for Lua on Finale it is recommended to use the function finenv.GetFinaleMainWindow() to get it. This function (available starting in RGP Lua 0.66) returns the MDI Client Window handle in Windows or nil in macOS.

These functions use the following os-specific types. They appear in Lua as opaque light userdata items. Lua scripts should only use them to pass to the menu functions in this library.

Type Description
menu_handle os-assigned value that provides access to the menu
window_handle handle (HWND) of a window containing a top-level menu (Windows) or nil (macOS)

Here is an example script that moves Finale's Music Spacing options to a top-level menu called "Spacing". (See test-menubuild-luaosutil.lua in this repository.)

local osutils = require('luaosutils')
local menu = osutils.menu

local main_window = finenv.GetFinaleMainWindow()
local menu_bar = menu.get_top_level_menu(main_window)
local spacing_menu, spacing_index = menu.find_item(menu_bar, "Apply Note Spacing to")
local new_spacing_menu = menu.insert_submenu("Spacing",  menu_bar, 4)
for i = 0, menu.get_item_count(spacing_menu)-1 do
    local move_result = menu.move_item(spacing_menu, 0, new_spacing_menu)
    print(move_result)
end
local del_result = menu.delete_submenu(spacing_menu, main_window)
print(del_result)

menu.delete_submenu*

Deletes the specified submenu item from its parent menu. The submenu must contain zero menu items or it will not be deleted.

Input Type Description
menu_handle Handle of the submenu to be deleted.
window_handle The window with the menu to search (Windows) or nil (macOS).
Output Type Description
boolean True if the submenu was deleted.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)

-- add code the moves all items out of rgp_lua_menu

-- now delete the submenu that contained "RGP Lua..." if it no longer contains items
menu.delete_submenu(rgp_lua_menu, finenv.GetFinaleMainWindow())

menu.execute_command_id

Executes the menu item specified by the input command-id. You can use get_item_command_id to get the command-id for a menu item. Note that (at least in Finale) command-ids do not change for core functions of the program. That means you can calculate the command-id once during development and then execute its hard-coded value at run-time. This has the advantage that

  • The Lua script is not dependent on which locale Finale is running in.
  • The Lua script is not dependent on changes in Finale's menus from version to version.

However, variable menu items (such as plugins or bookmarks) may have different command-ids each time the program runs.

Input Type Description
integer Menu command-id of the item to be executed.
window_handle The window with the menu to search (Windows) or nil (macOS).
Output Type Description
boolean True if the menu item was executed successfully.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua")
if rgp_lua_menu then
    local command_id = menu.get_item_command_id(rgp_lua_menu, index)
    -- opens the RGP Lua configuration window
    menu.execute_command_id(command_id, finenv.GetFinaleMainWindow())
end

menu.find_item

Searches a menu for an item whose text matches the input text and returns the enclosing menu if it is found. The function searches any submenus as well. To search all menus, pass in the value returned by menu.get_top_level_menu.

Input Type Description
menu_handle The menu from which to start searching.
string The text to search for encoded in utf8.
(number) Optional 0-based index that specifies the starting top-level menu from which to search. If omitted, the entire top-level menu is searched.
Output Type Description
menu_handle Handle to the menu that contains the item or nil if not found.
number The 0-based index of the found item.

The Windows version of this function skips "&" characters in the menu item text when doing comparisons. This allows you to supply the same text on either Windows or macOS platforms and find the menu options and ignore the "&" characters that designate keyboard shortcuts on Windows.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    -- rgp_lua_menu is the menu that contains the menu item for RGP Lua.
end

menu.get_item_command_id

Returns the command-id of the specified menu item or nil if none.

Input Type Description
menu_handle Handle to the menu.
number The 0-based index of the submenu item.
Output Type Description
number Command-id of the submenu or nil if none.

On Windows this function returns the command-id. On macOS it returns the menu item's tag value. Finale uses the tag value to mimic the behavior of the Windows command-id. This function may be less useful if luaosutils is running on macOS in an environment other than Lua on Finale.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua")
if rgp_lua_menu then
    local command_id = menu.get_item_command_id(rgp_lua_menu, index)
    local command_id = menu.get_item_command_id(rgp_lua_menu, index)
    -- opens the RGP Lua configuration window
    menu.execute_command_id(command_id, finenv.GetFinaleMainWindow())
end

menu.get_item_count

Returns the number of menu items in the specified menu. It includes divider items.

Input Type Description
menu_handle Handle to the menu.
Output Type Description
number The number of items in the menu.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local number_of_items = menu.get_item_count(rgp_lua_menu)
end

menu.get_item_submenu

Returns the submenu of the specified menu item, if it exists.

Input Type Description
menu_handle Handle to the menu.
number The 0-based index of the submenu item.
Output Type Description
menu_handle Handle to the submenu or nil if none.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local main_menu, index = menu.find_item(menu_bar, "Plug-ins")
if main_menu then
    local plugins_menu = menu.get_item_submenu(main_menu, index)
end

menu.get_item_text

Returns the text of the specified menu item.

Input Type Description
menu_handle Handle to the menu.
number The 0-based index of the menu item.
Output Type Description
string The text of menu item (UTF-8 encoding).

On Windows, the text includes the & character if there is keyboard shortcut.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local item_3_text = menu.get_item_text(rgp_lua_menu, 3)
end

menu.get_item_type

Returns the type of the specified menu item.

Input Type Description
menu_handle Handle to the menu.
number The 0-based index of the submenu item.
Output Type Description
number A value representing the menu item type (see table of values)

The following are the possible values returned by this function.

Constant Name Value Description
ITEMTYPE_INVALID -1 The input was not a valid menu type.
ITEMTYPE_COMMAND 0 Regular menu command item. This is the default if no others are applicable.
ITEMTYPE_SUBMENU 1 Submenu item.
ITEMTYPE_SEPARATOR 2 Separator item.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local main_menu, index = menu.find_item(menu_bar, "Plug-ins")
if main_menu then
    local plugins_menu = menu.get_item_submenu(main_menu, index)
    for item = 0, menu.get_item_count(plugins_menu)-1 do
        local item_type = menu.get_item_type(plugins_menu, item)
        if item_type == menu.ITEMTYPE_SUBMENU then
            -- do something with submenu
        end
    end
end

menu.get_title

Returns the title of the specified menu.

Input Type Description
menu_handle Handle to the menu.
window_handle Handle to the window containing the menu (nil on macOS).
Output Type Description
string The title of menu (UTF-8 encoding).

On Windows, the title includes the & character if it has keyboard shortcut.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local menu_title = menu.get_title(rgp_lua_menu, finenv.GetFinaleMainWindow())
end

menu.get_top_level_menu

Returns a handle to the top-level menu for the specified window (Windows) or the currently running application (macOS).

Input Type Description
window_handle The window with the menu to search (Windows) or nil (macOS).
Output Type Description
menu_handle Handle to the top-level menu or nil if not found.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

local finale_menu = menu.get_top_level_menu(finenv.GetFinaleMainWindow())

menu.insert_separator*

Inserts a menu separator at the specified index.

Input Type Description
menu_handle Handle to the menu.
(number) The 0-based index where to insert the separator. If omitted, the separator is appended at the end.
Output Type Description
number The 0-based index of the new separator or nil if error.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local submenu, submenu_index = menu.insert_submenu("Articulations", rgp_lua_menu, 3)
end

menu.insert_submenu*

Inserts a new submenu at the specified index.

Input Type Description
string Title of the new submenu encoded UTF-8.
menu_handle Handle of the menu in which to insert the new submenu.
(number) The 0-based index where to insert the new submenu. If omitted, the submenu is appended at the end.
Output Type Description
menu_handle Handle to the new submenu or nil if not found.
number The 0-based index of the new submenu.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local submenu, submenu_index = menu.insert_submenu("Articulations", rgp_lua_menu, 3)
end

menu.move_item*

Moves a menu item from one menu location to another.

Input Type Description
menu_handle Handle to the source menu.
number The 0-based index of the source menu item.
menu_handle Handle to the target menu.
(number) Optional 0-based index of the target menu item. If omitted, the item is appended to the end of the menu.
Output Type Description
boolean True if the menu item was moved.
number The new 0-based index of the item in the target menu.

This function can only move base menu items. It cannot move submenus. If you pass in an item for a submenu it returns false. To move a submenu, create the new submenu and then move all the items for the submenu individually.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local finale_menu = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(finale_menu, "RGP Lua...", min_search_index)
if rgp_lua_menu then
	 -- move the RGP Lua configuration menu option to the end of the Finale menu.
    menu.move_item(rgp_lua_menu, index, finale_menu)
end

menu.redraw*

Redraws the menu bar. This function does nothing on macOS.

Input Type Description
window_handle Handle to the window containing the menu (nil on macOS).
Output Type Description
none

Always call this function after modifying the menus, especially if you have modified the top menu. It it is sometimes not necessary, especially when running at startup, but it does not hurt anything.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

menu.redraw(finenv.GetFinaleMainWindow())

menu.set_item_text*

Changes the text of the specified menu item to the new value.

Input Type Description
menu_handle Handle to the menu.
number The 0-based index of the menu item.
string The new text of menu item (UTF-8 encoding).
Output Type Description
boolean True if the menu item text was changed.

On Windows, the text includes the & character if there is keyboard shortcut.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local success = menu.set_item_text(rgp_lua_menu, index, "Lua on Finale...")
end

menu.set_title*

Sets the title of the specified menu.

Input Type Description
menu_handle Handle to the menu.
window_handle Handle to the window containing the menu (nil on macOS).
string The new title of menu (UTF-8 encoding).
Output Type Description
boolean True if the menu title was changed.

On Windows, the title includes the & character if it has keyboard shortcut.

Example:

local osutils = require('luaosutils')
local menu = osutils.menu

 -- Specify the minimum 0-based index of Finale's Plug-Ins menu in the top-level application menu.
local min_search_index = 6

local menu_bar = menu.get_top_level_menu(finenv.GetFinaleMainWindow())
local rgp_lua_menu, index = menu.find_item(menu_bar, "RGP Lua...", min_search_index)
if rgp_lua_menu then
    local success = menu.set_title(rgp_lua_menu, finenv.GetFinaleMainWindow(), "Lua on Finale...")
end