# The actions package

The action package is used to register actions and menus in PCB and to execute existing actions. In PCB actions are generated when the user selects a menu, presses a key or issues a command on the PCB command line.

## Registration of new actions

The script may register new actions using arbitrary action names. If any of the registered actions is detected, an ACTE_action event is sent to the script. If multiple actions are used in a script, argument name of the event handler can be used to identify the triggering action. (This may be time consuming in scripting languages (a series of string comparison) - those scripts binding to frequent actions should not bind to too many different actions.) pcb-gpmi guarantees that the event handler of a script is triggered only when an action is caught that previously was registered by the same script.

The process of binding an action:

1. create an event handler for event ACTE_action
2. register one or more actions using function action_register
3. optional: when the event handler is triggered, check argument name (for scripts with multiple actions registered)
4. optional: use argument argc and function action_arg to fetch action arguments
5. optional: use arguments x, y to learn the cursor position on the layout.

Example (written in lua):

    -- load the package
    PkgLoad("pcb-gpmi/actions", 0);

    -- action callback
    function ev_action(id, name, argc, x, y)
    	if name == "cake" then
    		size = action_arg(1);
    		-- put cake drawing code here
    	else
    		-- must be candy
    		amount = action_arg(1);
    		-- put candy drawing code here
    	end
    end

    -- register and bind action
    action_register("cake",  "cake center xy?", "cake service", "cake(size)", "");
    action_register("candy", "candy cloud center xy?", "cake service", "candy(amount)", "");
    Bind("ACTE_action", "ev_action");

When the script is unloaded all actions the script registered are removed from pcb-rnd automatically.

## Executing actions

An existing action can be executed using the action() call. The only one argument is a command line string. The syntax is the same as in pcb command line. Example (written in lua):

    PkgLoad("pcb-rnd-gpmi/actions", 0);

    function ev_action1(id, name, argc, x, y)
    	action("undo()")
    	action("undo()")
    end

    -- register and bind action
    action_register("untwo", "", "undo twice", "untwo()", "CONTEXT!");

The above script registers a new action called untwo(). When untwo() is executed, it executes action undo() twice.

## Creating menus

It is possible to insert menus and submenus runtime, using the call create_menu(). The script should do this only after the gui has been initialized. The most common way is to create all menus from the ACTE_gui_init event, which is called after the gui finished setting up.

The first argument of create_menu() is the menu path. The path is a list of visible menu names separated by slashes (e.g. "/main_menu/File/Save as..." means "File" menu, "Save as..." submenu).

Paths are interpreted as menu paths, which are a slightly simplified version of lihata paths found in menu.lht. Basically there's a main directory directly under root that determines the type of the menu:

- /main_menu/ is the menubar
- /popups/something/ is a popup menu called something; the lesstif HID does not support popups; popups are popped up by actions.

The simplification compared to lihata paths is that only menu and submenu names are on the path, so lihata nodes like "li:submenu" should be ignored. In other words, the path represents how the menus can be reached from the user interface, plus a "main menu type prefix" as discussed above.

By convention, scripts should create new menu items under the "/main_menu/Plugins/" menu.

The following example lua script registers a new menu item

    PkgLoad("pcb-rnd-gpmi/actions", 0);

    function ev_gui_init(argc, argv)
    	create_menu("/main_menu/Plugins/foo", "undo()", "o", "Ctrl<Key>o", "tooltip for foo");
    end

    -- register and bind action
    Bind("ACTE_gui_init", "ev_gui_init");

When the user clicks on the menu, the action script specified in the second argument of create_menu() is executed. Thus the script usually registers a new action first then registers one or more menu items executing those actions.