.\" Copyright (c) 2005-2007 Hypertriton, Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 30, 2005
.Dt AG_MENU 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.0
.Sh NAME
.Nm AG_Menu
.Nd agar menu widget
.Sh SYNOPSIS
.Bd -literal
#include
#include
.Ed
.Sh DESCRIPTION
The
.Nm
widget implements a hierarchical menu system which supports text-based menu
and toolbar displays.
Individual menu items can bind to boolean values and specific bits in integer
values.
.Sh INHERITANCE HIERARCHY
.Xr AG_Object 3 ->
.Xr AG_Widget 3 ->
.Nm .
.Sh INITIALIZATION
.nr nS 1
.Ft "AG_Menu *"
.Fn AG_MenuNew "AG_Widget *parent" "Uint flags"
.Pp
.Ft "AG_Menu *"
.Fn AG_MenuNewGlobal "Uint flags"
.Pp
.Ft void
.Fn AG_MenuExpand "AG_Menu *menu" "AG_MenuItem *item" "int x" "int y"
.Pp
.Ft void
.Fn AG_MenuCollapse "AG_Menu *menu" "AG_MenuItem *item"
.Pp
.Ft void
.Fn AG_MenuSetPadding "AG_Menu *menu" "int left" "int right" "int top" "int bottom"
.Pp
.Ft void
.Fn AG_MenuSetLabelPadding "AG_Menu *menu" "int left" "int right" "int top" "int bottom"
.Pp
.nr nS 0
The
.Fn AG_MenuNew
function allocates, initializes, and attaches a new
.Nm
widget.
The
.Fn AG_MenuNewGlobal
variant creates a global application menu.
.Pp
The
.Fn AG_MenuExpand
function creates a new (frameless) window at the coordinates
.Fa x ,
.Fa y .
The window contains an
.Ft AGMenuView
widget which shows the child entries of
.Fa item .
If an item is clicked on, the window is automatically destroyed.
The
.Fn AG_MenuCollapse
function manually destroys the popup window.
.Pp
.Fn AG_MenuSetPadding
sets the global padding around all menu items, in pixels.
.Fn AG_MenuSetLabelPadding
sets the padding around the text label of items.
If a parameter is -1, its current value is preserved.
.Sh MENU ITEMS
.nr nS 1
.Ft "AG_MenuItem *"
.Fn AG_MenuNode "AG_MenuItem *parent" "const char *text" "AG_Surface *icon"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuAction "AG_MenuItem *parent" "const char *text" "AG_Surface *icon" "void (*fn)(AG_Event *)" "const char *fmt, ..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuActionKb "AG_MenuItem *parent" "const char *text" "AG_Surface *icon" "SDLKey keysym" "SDLMod keymod" "void (*fn)(AG_Event *)" "const char *fmt, ..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuDynamicItem "AG_MenuItem *parent" "const char *text" "AG_Surface *icon" "void (*fn)(AG_Event *)" "const char *fmt, ..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuDynamicItemKb "AG_MenuItem *parent" "const char *text" "AG_Surface *icon" "SDLKey key" "SDLMod kmod" "void (*fn)(AG_Event *)" "const char *fmt, ..."
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuTool "AG_MenuItem *parent" "AG_Toolbar *toolbar" "const char *text" "AG_Surface *icon" "SDLKey keysym" "SDLMod keymod" "void (*fn)(AG_Event *)" "const char *fmt, ..."
.Pp
.Ft "void"
.Fn AG_MenuSetIcon "AG_MenuItem *item" "AG_Surface *su"
.Pp
.Ft "void"
.Fn AG_MenuSetLabel "AG_MenuItem *item" "const char *label"
.Pp
.Ft "void"
.Fn AG_MenuSetPollFn "AG_MenuItem *item" "void (*fn)(AG_Event *)" "const char *fmt, ..."
.Pp
.Ft "void"
.Fn AG_MenuItemFree "AG_MenuItem *menu"
.Pp
.Ft "void"
.Fn AG_MenuState "AG_MenuItem *item" "int state"
.Pp
.Ft "void"
.Fn AG_MenuEnable "AG_MenuItem *item"
.Pp
.Ft "void"
.Fn AG_MenuDisable "AG_MenuItem *item"
.Pp
.nr nS 0
The
.Fn AG_MenuNode
function inserts a new node (no-op) item displaying the given
.Fa text
and
.Fa icon
(or NULL if none).
Node items are typically only used to attach subitems.
.Pp
The
.Fn AG_MenuAction
function inserts a new action item displaying the given
.Fa text
and
.Fa icon
(or NULL if none).
When selected, the item will invoke the event handler function
.Fa fn ,
with the additional arguments specified in
.Fa fmt
(unless it is NULL).
.Pp
The
.Fn AG_MenuActionKb
variant also associates the action with the given
.Xr SDLKey 3
and modifier.
.Pp
The
.Fn AG_MenuTool
variant automatically inserts an item into the given toolbar as well.
.Pp
The
.Fn AG_MenuDynamicItem
function creates a dynamic menu item.
The specified callback routine
.Fa fn
will be invoked repeatedly to update the menu item (see
.Xr AG_Event 3
for details), with the
.Nm
itself passed as
.Xr AG_SELF 3 .
A pointer to the
.Ft AG_MenuItem
can be retrieved using
.Xr AG_SENDER 3 .
The callback routine is allowed to directly modify the
.Va state
member of the
.Ft AG_MenuItem .
This variable defines the boolean state for the specified menu item
(0 = disabled, 1 = enabled).
If
.Va state
is -1, the boolean state is determined from any boolean/flag binding
associated with the item.
The callback can also change the text label and icon using
.Fn AG_MenuSetLabel
and
.Fn AG_MenuSetIcon .
The
.Fn AG_MenuSetPollFn
routine sets the callback function associated with a given item.
.Pp
The
.Fn AG_MenuItemFree
function destroys the given menu item as well as its children.
.Pp
The
.Fn AG_MenuState
(or its variants
.Fn AG_MenuEnable
and
.Fn AG_MenuDisable )
request that all subsequently created menu items are assigned the given
state.
.Sh BOOLEAN AND BITMASK ITEMS
.nr nS 1
.Ft "AG_MenuItem *"
.Fn AG_MenuBool "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuBoolMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntBool "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntBoolMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8Bool "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint8 *value" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8BoolMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint8 *value" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuFlags "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuFlagsMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntFlags "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntFlagsMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "int *value" "int flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8Flags "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint8 *value" "Uint8 flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt8FlagsMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint8 *value" "Uint8 flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt16Flags "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint16 *value" "Uint16 flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt16FlagsMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint16 *value" "Uint16 flags" "int invert" "AG_Mutex *mutex"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuInt32Flags "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint32 *value" "Uint32 flags" "int invert"
.Pp
.Ft "AG_MenuItem *"
.Fn AG_MenuIntFlagsMp "AG_MenuItem *" "const char *text" "AG_Surface *icon" "Uint32 *value" "Uint32 flags" "int invert" "AG_Mutex *mutex"
.Pp
.nr nS 0
The
.Fn AG_Menu*Bool
functions create a new item that binds to the given boolean variable.
If the
.Fa invert
parameter is non-zero, the actual value is inverted.
.Pp
The
.Fn AG_Menu*Flags
functions create a new item controlling one or more bits inside an integer
value.
The
.Fa flags
argument specifies the bitmask.
If
.Fa invert
is non-zero, the bits are inverted.
.Pp
The
.Fn AG_Menu*BoolMp
and
.Fn AG_Menu*FlagsMp
variants accept a
.Ft "AG_Mutex *"
argument specifying a mutex to acquire prior to reading or writing the data.
.Sh OTHER ITEMS
.nr nS 1
.Ft "void"
.Fn AG_MenuSeparator "AG_MenuItem *item"
.Pp
.Ft "void"
.Fn AG_MenuSection "AG_MenuItem *item" "const char *text" "..."
.Pp
.nr nS 0
The
.Fn AG_MenuSeparator
function inserts a horizontal menu separator.
.Pp
.Fn AG_MenuSection
creates a non-selectable item displaying the given text.
.Sh POPUP MENUS
.nr nS 1
.Ft "AG_PopupMenu *"
.Fn AG_PopupNew "AG_Widget *widget"
.Pp
.Ft void
.Fn AG_PopupShow "AG_PopupMenu *pm"
.Pp
.Ft void
.Fn AG_PopupShowAt "AG_PopupMenu *pm" "int x" "int y"
.Pp
.Ft void
.Fn AG_PopupHide "AG_PopupMenu *pm"
.Pp
.Ft void
.Fn AG_PopupDestroy "AG_Widget *widget" "AG_PopupMenu *pm"
.Pp
.nr nS 0
The
.Fn AG_PopupNew
function creates a new popup menu and associates it with the specified widget.
This association will cause the popup menu to be automatically freed when the
given widget is destroyed.
.Pp
Once a popup menu is created, new items can be inserted using the
.Va item
member of the
.Ft AG_PopupMenu
structure as parent.
.Pp
.Fn AG_PopupShow
displays the popup menu at the current mouse cursor coordinates.
.Fn AG_PopupShowAt
displays the popup menu at the specified display coordinates.
.Fn AG_PopupHide
hides the popup menu from the user.
.Pp
.Fn AG_PopupDestroy
detaches the specified popup menu from its associated widget, and releases
its allocated resources.
This function is automatically invoked whenever a widget is destroyed.
.Sh EVENTS
The
.Nm
widget reacts to the following events:
.Pp
.Bl -tag -compact -width "window-mousebutton* "
.It window-mousebutton*
If the cursor is over a menu item, display its sub-items.
.It window-mousemotion
Change the current sub-item display if the cursor is moved to a different
item.
.El
.Pp
The
.Nm
widget does not generate any event.
.Sh BINDINGS
The
.Nm
widget does not provide any binding.
.Sh STRUCTURE DATA
For the
.Ft AG_Menu
object:
.Pp
.Bl -tag -width "AG_MenuItem *itemSel "
.It Ft AG_MenuItem *root
The root menu item (read-only).
.It Ft AG_MenuItem *itemSel
The currently selected top-level item (read-only).
Top-level items are attached directly to
.Va root .
.It Ft int selecting
Selection is in progress if set to 1 (read-only).
.El
.Pp
For the
.Ft AG_MenuItem
structure:
.Pp
.Bl -tag -width "AG_MenuItem *subitems "
.It Ft char *text
Displayed text for the menu item (read-only, set by
.Fn AG_MenuSetLabel ) .
.It Ft AG_Surface *iconSrc
The
.Xr AG_Surface 3
of the menu icon, or NULL (read-only, set by
.Fn AG_MenuSetIcon ) .
.It Ft int value
The boolean state of the item, used by default.
If the boolean state was bound to another variable (e.g., using
.Fn AG_MenuBool
or
.Fn AG_MenuSetIntBool ) ,
this value is ignored.
.It Ft int state
If this flag is set (the default), the item is "enabled".
Otherwise, the user is not allowed to select the item.
.It Ft AG_Menu *pmenu
Back pointer to the parent
.Ft AG_Menu
(read-only).
.El
.Sh EXAMPLES
The following code fragment associates a menu with an
.Xr AG_Toolbar 3 .
Buttons and menu entries are created for the same actions.
.Pp
.Bd -literal -offset indent
AG_Toolbar *toolbar;
AG_Menu *menu;
AG_MenuItem *item;
toolbar = AG_ToolbarNew(win, AG_TOOLBAR_HORIZ, 1, 0);
menu = AG_MenuNew(win, 0);
item = AG_MenuAddItem(menu, "File");
{
AG_MenuToolbar(item, toolbar);
AG_MenuAction(item, "Load", NULL, LoadFile, NULL);
AG_MenuAction(item, "Save", NULL, SaveFile, NULL);
AG_MenuToolbar(item, NULL);
}
.Ed
.Pp
The following code fragment creates a menu with an action item, a boolean
item and two bitmask items.
.Pp
.Bd -literal -offset indent
Uint16 flags = 0;
#define FOO_FLAG 0x01
#define BAR_FLAG 0x02
void
SayHello(AG_Event *event)
{
char *s = AG_STRING(1);
AG_TextMsg(AG_MSG_INFO, "Hello, %s!", s);
}
void
QuitApplication(AG_Event *event)
{
AG_Quit();
}
.Li ...
AG_Menu *menu = AG_MenuNew(win);
AG_MenuItem *item = AG_MenuAddItem(menu, "File");
{
AG_MenuInt16Flags(item, "Foo", NULL, &flags, FOO_FLAG, 0);
AG_MenuInt16Flags(item, "Bar", NULL, &flags, BAR_FLAG, 0);
AG_MenuAction(item, "Say hello", NULL,
SayHello, "%s", "world");
AG_MenuAction(item, "Quit", NULL,
QuitApplication, NULL);
}
.Ed
.Sh SEE ALSO
.Xr AG_Intro 3 ,
.Xr AG_Event 3 ,
.Xr AG_Button 3 ,
.Xr AG_Surface 3 ,
.Xr AG_Toolbar 3 ,
.Xr AG_Tlist 3 ,
.Xr AG_Widget 3 ,
.Xr AG_Window 3
.Sh HISTORY
The
.Nm
widget first appeared in Agar 1.0.