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:
- item, ordinary user selectable menu item,
- check, selectable item with toggleable check mark,
- radio, radio group with mutually exclusive check mark,
- title, unselectable item with text label,
- delim, unselectable horizontal line between two menu items, and
- space, a small gap between two 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.
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:
- checked, menu is initially checked if item type is radio or checkable item,
- disabled, menu is initially disabled and cannot be selected until enabled,
- norun_callback_onload, do not run menu item callback when loading user settings which caused item state to change,
- sync_settings_on_change, save all registered settings when this item state changes,
- sync_settings_on_set, save all registered settings when this item is set, and
- sync_settings_on_unset, save all registered settings when this item is unset.
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.