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"

menu_*() functions can be used to manipulate some of the menu parameters at runtime.

Layout

Menu resource layout 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 the drop down menu.

Menu resource layout is defined as follows:

;
; 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	"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 it 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.

Menu container

Menu container is the box where all the selectable and other items are listed from top to bottom. Menu box itself is wrapped by its parent container, window or widget. Menu box is defined as follows:

menu "menu_name" { optional_icon
	; 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. Submenu does not support icon and even if defined, it will not be displayed. Supported file formats for icons are BMP and 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:

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.

Id

Item id is custom number to pass to callback function when item was selected. Handy, if you want to use same callback for several menu items. Radio group must use same id number for every item in the group. This component is mandatory.

Key

⭐ New in 0.2.9.

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 formats for icons are BMP and 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.

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 (_x, _y, _x_root, _y_root, _state, _button) {
}

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