Menu resources

Using menu resource file is fast and easy way to construct menu layout which can be attached to window as a menu bar, or it can be attached to widget as well. Engine's menu_*() functions can be used to manipulate some of the menu parameters at runtime after the menu is created as defined in resource file.

Menu resource file compiles to C, and is further compiled and linked as static part of the application. Provided menu resource compiler is written in perl, which handles resource syntax explained below. When resource file is compiled, the resulting file menu_defs.h is produced. Compatible file can be ofcourse produced by some other mechanism if provided compiler or source syntax feels discomfortable.

Menu resource compiler expects input file to be UTF-8 encoded, and supports include-directive, so resource file can be divided into several files:

include "the_other_menu_file.m2c"

Usage

Menu system usage is somewhat similar than in any other user interface system. Menu bar is usually located in top of the window, and when pointed and clicked, it opens menu window where selectable items are listed.

Menu bar can be attached to widget too. When widget is clicked with pointer button 2 (also known as middle mouse button), it opens the menu, or with any other pointer button with control key pressed.

When shift key is pressed while selecting menu items, menu window does not close after selection, so another selection can be made right away without reopening the menu window. Just like menu selection in good old AmigaOS intuition works.

Keyboard controls are available with menu windows, by default:

Keys can be remapped by application resource file.

Layout table

Menu resource layout table is made of structured keywords, like window and widget, to attach the menu either to window or widget, respectively, and menu keyword which defines the actual content of drop down menu window.

Menu resource layout table style is defined as:

;
; @MENU_DEFAULT_TITLE_ORIENTATION	left_to_right
;
; Menu is attached to window where WIDGET_STACK_ID is set to 1.
;
; container_type "container_id" {
;
window "1" {
	;
	; menu "menu_name" {								optional_icon
	;       ---------								-------------
	;
	menu "My menu" {								icons/my_menu_icon.tga
		;
		; type	"title",		id,	key,	callback,	flags,	optional_icon
		; ----   -----			--	---	--------	-----	-------------
		;
		item	"Item one",		1,	none,	my_cb_1,	none,	icons/item_one.tga
		item [icon: icons/item_two.tga] \
			"Item two",		2,	none,	my_cb_2

		menu "My submenu" {
			item	"Item three",	3,	none,	my_cb_3

			delim

			radio	"Radio A",	10,	none,	my_cb_radio,	checked
			radio	"Radio B",	10,	none,	my_cb_radio
			radio	"Radio C",	10,	none,	my_cb_radio
		}
	}
}

When menu is attached to window, container id must be the WIDGET_STACK_ID which is passed to window_open() function when window is created in Ano script.

Header tags

Header tags can be used to affect menu appearance and set some common defaults. Tags are placed usually in beginning of menu layout table, and must be commented out, and they must start with @. Tags include:

Marker icon supports either image file, UTF-8 character, or UTF-32 codepoint. UTF-8 character must be prefixed with \u and UTF-32 codepoint with \x. When setting UTF icons, selected font must support those characters. Set font in application resource file with menu.markerFontFace and menu.markerFontSize settings.

Example header tags:

;
; @MENU_DEFAULT_TITLE_ORIENTATION        left_to_right
;
; Default menu item icon is fleuron, utf32 hexadecimal codepoint 2740:
;
; @MENU_DEFAULT_SELECTION_ICON           \x2740
;
; All the icon images are 16 times 16 pixels in size.
;
; @MENU_ICON_WIDTH_HINT                  16
; @MENU_ICON_HEIGHT_HINT                 16
;
; @MENU_MARKER_RADIO_ON                  /path/to/icons/radio_on.tga
; @MENU_MARKER_RADIO_OFF                 /path/to/icons/radio_off.tga
;
; Check item, or togglable item marker icon is set directly using utf8
; characters, they equal utf32 codepoint 2718 and 274d:
;
; @MENU_MARKER_TOGGLE_ON                 \u✘
; @MENU_MARKER_TOGGLE_OFF                \u❍
;
; Use right pointing arrow as submenu indicator mark, that is utf32 hexadecimal
; codepoint 27a4:
;
; @MENU_MARKER_SUBMENU_ARROW             \x27a4
;
window "1" {
	; Window 1 menu definitions comes here...
	;
}

Menu container

Menu container is the box on screen where all the selectable and other items are listed from top to bottom. Menu container box itself is attached to its parent container, window or widget, or parent menu container. Menu box supports couple of attributes which is defined just after menu keyword. Attributes include:

All color definitions in attributes overrides resource settings. Menu box is defined as follows:

menu "menu_name" { optional_icon
	; menu items comes here
}

menu [hilight: #2244aa, background: indianred] "another_menu_name" {
	; menu items comes here
}

Menu name is the string that appears in menu bar, and when clicked, opens the actual menu. Menu name is mandatory component. If optional icon is defined, it will appear left side of the name string. Leave empty if there is no need for an icon. Supported file format for icons is TGA, unpacked true color, alpha channel recommended for transparency. If icon name starts with @, it is substituted with application installation prefix, so if icon is /where/ever/app/is/installed/share/icons/somemenu.tga, that can be written to layout table as @/share/icons/somemenu.tga. Using this trick is recommended, because paths will work even if installation prefix changes.

Menu item

Menu item components from left to right are explained below (see example layout above). Each component is separated with whitespace.

Type

Possible menu item types are:

Following attributes are supported by menu items:

Title

Menu title is the string that appears in the menu item container, and when it is clicked, menu item callback function is called. This component is mandatory with all item types except with delim and space.

Id

Item id is a custom number to pass to callback function when item was selected. Handy, if you want to use same callback for several menu items. This is used also as an identifier by several functions to manipulate menues in runtime, so it is recommended to keep this number unique when possible. Radio group must use same id number for every item in the group. This component is mandatory with all item types except with delim and space.

Key

Item key is the key for consumer name when registering settings. Pass this key to settings_register() function along with setting class SETTINGS_MENU to load and save menu item state automatically. Menu item type must be either check or radio when registering settings for menu items. Radio group must use same key for every item. See Desktop menu demo for live example.

Callback

Menu item callback function is defined in application Ano script, and will be called when item is selected. See explanation of callback annotations here. Callback function must take four parameters, each explained below:

;
; Callback function parameters:
;
; item contains item name as defined in menu resource file.
; position contains item position in menu stack.
; tag contains item id number specified in menu resource file, or item
;  order number in group for radio group items.
; flag contains togglable item state, on or off, 1 or 0,
;  respectively, or item order number in radio group, counting from zero.
;
; Parameter types:
;
; item ........... string
; position ....... uint
; tag ............ uint
; flag ........... uint
;

;
; Example menu item callback function
;
_MENUCB_ITEM_ callback my_cb_1 (item, position, tag, flag) {
}

Flags

Menu item flags defines some special flags for the item. Several flags can be specified for one item by separating them with pipe (|). Possible menu item flags are:

When registering settings causes callback function to run, it does not start immediately, but it runs when menu window is opened.

Icon

If icon is defined, it appears on left side of the menu item text. Leave out or use none if there is no need for an icon. Item type of item, check and radio supports icons attached to them. Supported file format for icons is TGA, unpacked true color, alpha channel recommended for transparency. If this strings starts with @, it is substituted with application installation prefix, so if icon is /where/ever/app/is/installed/share/icons/someitem.tga, that can be written to layout table as @/share/icons/someitem.tga. Using this trick is recommended, because paths will work even if installation prefix changes.

Icon supports UTF-8 character or UTF-32 codepoint in hexadecimal format instead of image file. Set UTF-8 character with \u prefix and UTF-32 codepoint with \x prefix, like \x2713 for checkmark . When using UTF icons, selected font must support those characters. Set font in application resource file with menu.iconFontFace and menu.iconFontSize settings.

Widgets

Attaching menu to widget is just about same than attaching menu to window, except we need another container within window which identifies the widget where the menu is to be attached. Widget identifier must be widget name, as defined in widget resource file, by its name attribute. In following example, menu is attached to block widget my_menu_launcher. Widget needs buttonpress callback defined for menu popup to work. Buttonpress callback function does not have to do anything, it just needs to be there, as menu system takes use of that callback to hook the popup menu.

Menu pops up by pressing middle mouse button on top of container widget, or alternatively keep <ctrl> key pressed while pressing left mouse button.

Example

;
; Menu is attached to block widget my_menu_launcher.
;
; container_type "container_id" {
;
window "1" {
	widget "my_menu_launcher" {
		;
		; menu "menu_name" {								optional_icon
		;       ---------								-------------
		;
		menu "My menu" {								my_menu_icon.tga
			;
			; type	"title",		id,	key,	callback,	flags,	optional_icon
			; ----   -----			--	---	--------	-----	-------------
			;
			item	"Item one",		1,	none,	my_cb_1,	none,	item_one.tga
			item	"Item two",		2,	none,	my_cb_2

			menu "My submenu" {
				item	"Item three",	3,	none,	my_cb_3

				delim

				radio	"Radio A",	10,	none,	my_cb_radio,	checked
				radio	"Radio B",	10,	none,	my_cb_radio
				radio	"Radio C",	10,	none,	my_cb_radio
			}
		}
	}
}

This is the widget definition for popup menu above:

;
; @WIDGET_USE_BOUNDING_BOXES no
;
window "1" {
	set "0" {
		widget "block" {
			name		"my_menu_launcher"
			state		enable

			position	x = 0, y = 0
			size		width = 200, height = 40

			color		"rgba:#ffffddff"

			border		color = rgba:#5aa6bbff, thickness = 2

			; This empty callback is needed for menu to pop up
			;
			action		buttonpress = cb_button_press
		}
	}
}

Empty callback function cb_button_press is defined in Ano script. This is needed as menu system uses the buttonpress callback function to hook the menu in it:

_WIDGETCB_BUTTON_ callback cb_button_press (_hnd, \
	_x, _y, _x_root, _y_root, _state, _button) {
}

Copyright © 2026, Jani Salonen <salojan at goto10 piste co>. Piste is finnish word and means dot. All rights reserved.