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.