Main | News | Doc | People | Events & timeline | pcb-rnd

# pcb-rnd - the [res] patch

PCB used to have an own file format for describing resources (menu structure and hotkey bindings, vendor drill mapping). The resource format was generic enough to describe these things, but the syntax was somewhat weird: mixed positional and named fields. More precisely, composite nodes could contain named and anonymous subnodes, and the meaning of anonymous subnodes depended on their position in the anon-subnode-list.

The code that dealt with the in-memory representation of the resource tree was weird and big chunks duplicated in the HIDs and vendor drill module. It was also hard to parse a resource file with external tools.

Since version 1.0.10, pcb-rnd replaces resource files with lihata. Lihata is a small, generic purpose container format that can describe arbitrary trees. Just like resource file syntax, lihata is optimized for hand-editing: no need to use excess quoting or long boilerplate blocks.

Liblihata also provides a lot of helper functions that made the code dealing with the menus and vendor drill resources much simpler and less redundant. Since the parser is small and external, and since there are external converter tools available, it is also easier to deal with the files outside of the pcb executable.

## menu files

There are pcb-menu-gtk.lht and pcb-menu-lesstif.lht. They are in trunk/src in the source tree and are installed in the SHAREDIR. Currently each GUI HID (lesstif, gtk) loads the corresponding menu file.

## menu resource lihata structure

The root of a menu resource file should be a ha: with the following children:

- li:mouse for mouse button bindings
- li:main_menu for describing the main menu
- li:popups for describing the popup menus

All children are optional, but recommended. Thus the file structure, zoomed out, is:

    ha:{
    	li:mouse { ... }
    	li:main_menu { ... }
    	li:popups { ... }
    }

### li:mouse

The mouse subtree may contain a li: for each mouse button action; the children of the list are further li: nodes for key modifiers, whose children are text nodes: actions executed in order.

Buttons supported are: left, right, middle, up, down - the last two are for the scroll wheel. Modifier name should start with "press" or "release" optionally followed by modifier key suffixes separated with dashes, e.g. "press-alt-shift" means the given button is pressed while alt and shift were also pressed.

Example structure:

    	li:mouse {
    		li:left {
    			li:press            = { Mode(Notify) }
    			li:press-ctrl       = { Mode(Save); Mode(None); }
    		}
    	}

### li:main_menu

The main menu is a list of menubar items that may host submenu items recursively. Each normal item is a hash with the following children:

- li:submenu an ordered list of submenu nodes (should not have accel key or action)
- tip tooltip text
- action text or list of actions to execute when menu is selected
- a a key description for an accelerator key (hotkey)
- li:a a list of key descriptions for an accelerator keys (hotkeys); all keys will be bound to the menu and the first key is shown in the menu

Special menu items are text nodes instead of hashes; they are:

- starting with @, are dynamic, auto-generated items (e.g. layers; might be HID-dependent)
- a single dash: separator

A key description is a text in the form of:

- the name of the node is the visible name of the menu item
- <key>keyname, e.g. "<key>k" for key K, or "<key>F10" for F10
- modifier<key>keyname, e.g. "Alt-<key>K" for Alt+K
- modifier-modifier<key>keyname, e.g. "Shift-Alt-<key>K" for Shift+Alt+K; modifiers are Alt, Shift and Ctrl; order does not matter, all three can be used together.
- multikey sequence: multiple of the above, separated by semicolons (protected with {} for lihata, as the text contains semicolon); e.g. "{<key>f;<key>o}" means the user presses "f" then "o". Sequences can be a dozen stroke long and any segment may use modifiers

An example menu item with submenus (can be a main menu or a submenu of another menu item):

    ha:example menu item {
    	li:submenu {
    		ha:menu item {
    			action=Save(ElementConnections)
    			tip=example menu
    		}
    		-
    		ha:another menu item {
    			a={Shift-Alt<key>r}
    			action={Action1(); Action2();}
    		}
    	}
    }

### li:popups

Each children is a hash that describes a popup menu. A popup menu behaves exactly like a menu item, it should have a submenu list. Popup windows will be popped up by executing an action with the name of the popup menu.

## save/load and compatibility

Not affected.

## plans

The resource file format conversion is done. There are other parts of the code that will probably get lihata instead of the current custom parsers, e.g. the preferences/settings file.