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 was set to 1.
;
; container_type "container_id" {
;
window "1" {
	;
	; menu "menu_name" {								optional_icon
	;       _________								_____________
	;
	menu "My menu" {								my_menu_icon.tga
		;
		; type	"title",	item_id,	callback,	flags,		optional_icon
		; ____   _____		_______		________	_____		_____________
		;
		item	"Item one",	1,		my_cb_1,	none,		item_one.tga
		item	"Item two",	2,		my_cb_2

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

			delim

			radio	"Radio A",	10,	my_cb_radio,	checked
			radio	"Radio B",	10,	my_cb_radio
			radio	"Radio C",	10,	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

Menu 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 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.

Possible menu item types are:

Menu name 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.

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.

Menu item callback function is defined in Ano script, and will be called when item was selected. Callback function must have four parameters defined, 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
; flag		contains togglable item state, on or off, 1 or 0,
;		respectively, or item order number in radio group,
;		counting from zero

;
; Example menu item callback function
;
callback my_cb_1 (_item, _position, _tag, _flag) {
	dump	_item
	dump	_position
	dump	_tag
	dump	_flag
}

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:

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 its name, as defined in widget resource file, by widget 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 menu popup.

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",	item_id,	callback,	flags,		optional_icon
			; ____   _____		_______		________	_____		_____________
			;
			item	"Item one",	1,		my_cb_1,	none,		item_one.tga
			item	"Item two",	2,		my_cb_2

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

				delim

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

This is the widget definition for popup menu above:

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:

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

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