Widgets are attached to their containers with
AG_ObjectAttach(3) and detached with
AG_ObjectDetach(3). Unattached widgets can be freed using
AG_ObjectDestroy(3). Agar handles garbage collection of windows (and attached widgets) internally.
Destroying an active
AG_Window(3) or a widget which is still attached to a parent is an error which would
trigger a fatal assertion in debug mode.

Unless renamed with
AG_ObjectSetName(3), widget instances are given a generic name (e.g., "button0").
AG_ObjectFind(3) can be used to get a pointer to a widget by pathname (e.g., "box0/button0").

Parentless widgets form the root of their own virtual filesystem.
It is customary for high-level constructor routines (such as
AG_ButtonNew(3)) to accept a NULL
parent argument, allowing the caller to make an explicit
AG_ObjectAttach(3) call at a later time.

The
AG_Variable(3) table of
AG_Object is used to store bindings data, style properties and general user data.
The
AG_Event(3) framework is used to handle both low-level (e.g., "mouse-button-down") as well
as high-level (e.g., "button-pushed") events.

draw() renders the widget to the graphics display (e.g., using OpenGL,
AG_WidgetPrimitives(3) or other methods).
The code under
draw() is referred to as
Rendering Context. Widget primitives and operations such as
AG_WidgetBlitSurface() must be called from rendering context.

size_request() should return an initial, preferred geometry in pixels (without any guarantee
that the request will be satisfied).
For example, an
AG_Label(3), might return the expected size of a rendered text label.

size_allocate() is called once the widget has been successfully allocated a new size
or position within its parent (as described by the
w, h, x and
y members of the
AG_SizeAlloc argument).
Container widgets allocate the position and size of their children in
size_allocate().

size_allocate() should return 0 on success and -1 if the allocation is not satisfactory for
draw() to work at all (in which case the
UNDERSIZE flag will be set and
draw() will not run).

SIZING

voidAG_Expand (AG_Widget *obj)

voidAG_ExpandHoriz (AG_Widget *obj)

voidAG_ExpandVert (AG_Widget *obj)

voidAG_WidgetSizeReq (AG_Widget *obj, AG_SizeReq *req)

voidAG_WidgetSizeAlloc (AG_Widget *obj, AG_SizeAlloc *alloc)

voidAG_WidgetSetPosition (AG_Widget *obj, int x, int y)

voidAG_WidgetSetSize (AG_Widget *obj, int w, int h)

voidAG_WidgetSetGeometry (AG_Widget *obj, AG_Rect rect)

voidAG_WidgetUpdate (AG_Widget *obj)

voidAG_WidgetUpdateCoords (AG_Widget *obj, int x, int y)

AG_Expand() makes the widget fill all available space in its parent.
AG_ExpandHoriz() and
AG_ExpandVert() expands only in the given direction.
Most widget constructors also accept
EXPAND, HFILL and
VFILL options.

AG_WidgetSizeReq() invokes the
size_request() operation of the widget and returns its size requisition into
req. AG_WidgetSizeAlloc() allocates the given position and geometry of the widget.
If the
w or
h argument is <= 0, the
AG_WIDGET_UNDERSIZE flag is set, preventing the widget from subsequent rendering.

AG_WidgetSizeReq() and
AG_WidgetSizeAlloc() are meant to be called only from within the
size_request() and
size_allocate() functions of a container widget implementation, in order to
size and position the child widgets attached to the container
(if you must set widget geometries explicitely, use either the
AG_Fixed(3) container, or create your own container widget).

AG_WidgetSetPosition() sets the effective position of the widget relative to its parent container.
AG_WidgetSetSize() sets the size of the widget in pixels.
AG_WidgetSetGeometry() sets both position and size of a widget from the specified
AG_Rect. These functions are typically only used in the context of the
size_request() and
size_allocate() routines of container widgets.

AG_WidgetUpdate() requests an update of the computed coordinates and geometries of all widgets
attached to the widget's current window.
The widget may or may not be attached to a parent window (the actual update
will be performed later, before rendering starts in
AG_WindowDraw()). AG_WidgetUpdate() should be called following
AG_ObjectAttach(3) or
AG_ObjectDetach(3) calls made in event context, or manual modifications of the
x, y, w, h fields of the
AG_Widget structure.

AG_WidgetUpdateCoords() is called internally to update the cached absolute display coordinates (the
rView rectangle) of
wid and its descendents based on their current relative coordinates (the
x, y, w, h members).
The widget and its parent VFS must be locked.

INPUT STATE

voidAG_WidgetEnable (AG_Widget *obj)

voidAG_WidgetDisable (AG_Widget *obj)

intAG_WidgetEnabled (AG_Widget *obj)

intAG_WidgetDisabled (AG_Widget *obj)

A widget in DISABLED state will not accept user input other than that
required for navigation (i.e., scrolling).
AG_WidgetEnable() clears the DISABLED flag and
AG_WidgetDisable() sets it.
These functions will raise the
widget-enabled and
widget-disabled events accordingly.

AG_WidgetEnabled() and
AG_WidgetDisabled() return the current state.

FOCUS STATE

Focus enables reception of input events that would be filtered out by default.
A focused widget (in an actively focused window) will receive
mouse-motion(), mouse-button-up(), as well as keyboard events
key-up() and
key-down().

AG_WidgetFocus() focuses the specified widget and all of its parent widgets including
the parent
AG_Window(3). Returns 1 on success and 0 if the widget is not accepting focus.

AG_WidgetUnfocus() removes the focus state from the given widget and its children, recursively.

AG_WidgetIsFocused() returns 1 if the widget is both focused in relation to its parent window, and
the parent window itself is focused.
AG_WidgetIsFocusedInWindow() returns 1 if the widget is focused regardless of the focus state of its parent.

AG_WidgetForwardFocus() arranges automatic forwarding of the focus to a specified widget.
Whenever
obj gains focus, Agar will arrange for the focus to be transferred automatically to
widgetToFocus.

BLITTING SURFACES

These routines allow graphical surfaces to be managed (mapped in hardware or
software) and efficiently copied.
They must be called from rendering context (i.e., the
draw() operation of
AG_Widget) only.

The
AG_WidgetBlit() function performs a software->hardware blit from the surface
src to the video display at the given widget coordinates.
AG_WidgetBlit() must invoked in rendering context.
See
AG_Surface(3) for more information on the Agar surface structure.

Software to hardware blits are slow, so the widget system provides an
interface to efficiently take advantage of graphics hardware where it
is available.
AG_WidgetMapSurface() registers the specified
AG_Surface(3) with the widget, returning an integer handle to that surface.
The surface can be subsequently rendered by calling
AG_WidgetBlitSurface() or
AG_WidgetBlitFrom() using this handle.
The exact manner in which the surface is rendered depends on the Agar
driver in use.
For OpenGL-based drivers, a matching hardware texture will typically be
generated for the surface on the first call to
AG_WidgetBlitSurface(), and cached.

By default, mapped surfaces are automatically freed once the widget
is destroyed.
The
AG_WidgetMapSurfaceNODUP() variant sets the "NODUP" flag on the given surface, so the widget system
will never attempt to free the surface.

Note that
AG_WidgetMapSurface() will never duplicate the surface.
The function merely registers the provided surface pointer with the widget
structure.
The surface pointer must remain valid for the lifetime of the widget (if in
doubt, use
AG_SurfaceDup(3)). AG_WidgetMapSurface() may be invoked from any context, but in a multithreaded context the returned
name is only valid as long as the widget remains locked.

AG_WidgetReplaceSurface() replaces the contents of a previously-mapped surface with the contents of
newSurface. The
AG_WidgetReplaceSurfaceNODUP() variant avoids duplicating the surface.

AG_WidgetUnmapSurface() destroys the given surface mapping.
It is equivalent to invoking
AG_WidgetReplaceSurface() with a NULL surface.
The function is safe to use from any context.

It is important to note that in OpenGL mode,
AG_WidgetReplaceSurface() and
AG_WidgetUnmapSurface() will not immediately delete any previous texture associated with the previous
surface.
Instead, it will queue the delete operation for future execution from
rendering context, as required by thread safety.

The
AG_WidgetUpdateSurface() function should be invoked whenever a mapped surface is changed.
If hardware surfaces are supported, it will cause an upload of the software
surface to the hardware (otherwise it is a no-op).

The
AG_WidgetBlitSurface() variant invokes
AG_WidgetBlitFrom with the same argument for both
srcWidget and
obj (and
rs set to NULL).

USING BINDINGS

Widget states can be bound to memory locations containing data in a
supported format.
For example, the "state" binding of
AG_Button(3) can be tied to an integer (or bits in an integer), such that the user pressing
the button directly manipulates the integer value in memory.

Bindings are documented under the heading
BINDINGS section of the widget's manual page.
For instance,
AG_Slider(3) mentions "value" bindings to integers.
Therefore, to control a byte of memory, one might use:

This method is not limited to primitive data types.
For example,
AG_Textbox(3) can bind to a fixed-size memory buffer containing a C string in ASCII,
UTF-8 or other supported encoding.

The
AG_Bind<Type>() family of functions bind widget states to memory data.
The
AG_Bind<Type>Mp() variants accept a pointer to a mutex which will be acquired prior to accessing
the data.

Since the state of a widget can influence its appearance
(e.g.,
AG_Button(3) is drawn as a pressed button if its "state" is 1), it may be necessary to
monitor the value and redraw when it changes.
AG_RedrawOnChange() arranges for this to occur automatically (see below).

CONTROLLING REDRAW

The
AG_Redraw() function signals that the widget must be redrawn to the video display.
It is equivalent to setting the
dirty variable of the widget's parent window to 1.
If called from rendering context,
AG_Redraw() is a no-op.

The
AG_RedrawOnChange() function arranges for the widget to be automatically redrawn whenever the
value associated with the existing binding
binding_name changes.
The value of the binding will be checked at the specified interval
refresh_ms in milliseconds.
If a
refresh_ms argument of -1 is passed, the effect of any previous
AG_RedrawOnChange() call with the specified binding is disabled.

The
AG_RedrawOnTick() function arranges for the widget to be unconditionally redrawn at the
specified interval in milliseconds.
If a
refresh_ms argument of -1 is passed, the effect of any previous
AG_RedrawOnTick() call is disabled.

AG_ParentWindow() returns a pointer to the parent
AG_Window(3) for the given widget instance.
The pointer is valid only as long as the parent VFS remains locked.
If the widget is not attached, NULL is returned.

AG_WidgetFindFocused() returns the top-most focused widget under
win.

AG_WidgetFindPoint() returns the top-most widget at display coordinates
x, y, which also is an instance of a the given
className (see
AG_ObjectClass(3), AG_OfClass(3)). The
AG_WidgetFindRect() variant requires that the widget enclose the whole given rectangle.

The pointer returned by
AG_WidgetFindFocused(), AG_WidgetFindPoint() and
AG_WidgetFindRect() is valid only for as long as the parent VFS is locked.

The
AG_PushClipRect() function pushes a rectangle (in widget-relative coordinates) onto the stack of
clipping rectangles, and
AG_PopClipRect() pops the last entry from the clipping rectangle stack.
The effective clipping rectangle will be the intersection of all rectangles
on this stack.
Both functions must be invoked in rendering context.

AG_PushBlendingMode() selects the source and destination functions for further pixel blending
operations.
It also pushes the current state onto the stack of alpha blending modes.
Setting
src to
AG_ALPHA_ZERO and
dst to
AG_ALPHA_ONE (the default) effectively disables blending.
Setting
src to
AG_ALPHA_SRC and
dst to
AG_ALPHA_ONE_MINUS_SRC is the most common case.
See
AG_AlphaFn(3) for the list of possible alpha blending modes.
AG_PopBlendingMode() pops the the last entry off of the stack of alpha blending modes.
Both functions must be invoked from rendering context.

The
AG_WidgetDraw() routine renders a widget to the display.
It is typically invoked from an event loop routine (such as
AG_EventLoop(3)), to recursively draw the hierarchy of visible GUI elements.

In the event loop,
AG_WidgetDraw() invocations must be enclosed between calls to
AG_BeginRendering() and
AG_EndRendering().

The
AG_WidgetHide() and
AG_WidgetShow() functions toggle the visibility of the specified widget (setting the
AG_WIDGET_HIDE flag as appropriate).

The
AG_WidgetHideAll() and
AG_WidgetShowAll() routines toggle the visibility of the specified widget and its children
by setting the
AG_WIDGET_VISIBLE flag (which works independently of
AG_WIDGET_HIDE). These routines are intended to be used by container widgets (for example,
AG_Notebook(3) which needs to show or hide tabbed containers).

AG_WidgetVisible() returns 1 if the widget is currently visible (equivalent to checking the
AG_WIDGET_VISIBLE flag).

The
AG_WidgetSurface() routine renders the widget to a newly-allocated
AG_Surface(3). This surface should be freed after use.

WIDGET ACTIONS

User-generated events such as key presses or mouse button events can be
connected to high-level Widget
actions, such as executing a specified routine or controlling a boolean.
Widget actions are described by the
AG_Action structure.

Where the conditions for execution of an Action are fixed (e.g., a specific
mouse button was clicked, or a specific key was pressed), use of
AG_ActionOn*() is preferred over low-level event handlers
(such as "key-down" or "mouse-button-down"), because it allows keyboard
and mouse bindings to be configured by the end-user in a standard way.
AG_Menu(3) also provides interfaces for working with widget actions.

AG_ActionFn() registers a new widget action which is to invoke a callback function
fn, with arguments
fnArgs. See
AG_Event(3) for a description of the
fnArgs format.

AG_ActionSetInt() registers a new action which is to set an integer
variable to a specified
value. Instead of an integer variable,
AG_ActionSetFlag() sets the bits specified by
bitmask to the specified
value (of 1 or 0).
The
AG_ActionToggleInt() and
AG_ActionToggleFlag() variants do not take an explicit
value argument, and toggle the current value instead.

AG_ActionOnButtonDown() and
AG_ActionOnButtonUp() tie an action to a button press and a button release event, respectively.
The
button argument specifies the button index (see
AG_MouseButton(3)). AG_ActionOnKeyDown() and
AG_ActionOnKeyUp() tie an action to a key press and key release event, respectively.
The
sym argument specifies the key (see
AG_KeySym(3)), and
mod specifies the modifier keys which must be in effect.
To match any key or any modifier state,
AG_KEY_ANY or
AG_KEYMOD_ANY can be used.

With
AG_ActionOnKeyDown() and
AG_ActionOnKeyUp(), the action is triggered once immediately on key press or key release.
The
AG_ActionOnKey() variant ties an action to a key press, but with "key repeat" behavior.
The action is triggered immediately once after an initial key press.
If the key combination is held longer than the "key delay" (by default 250ms),
the event is repeated with the "key repeat" interval (by default 30ms).

If there are currently no event handlers registered for "key-up", "key-down",
"mouse-button-up" and "mouse-button-down", the
AG_ActionOn*() functions automatically register event handlers which will invoke
AG_ExecMouseAction() or
AG_ExecKeyAction() as appropriate (see below).

AG_ExecMouseAction() executes any action associated with mouse button events.
It is typically invoked from the "mouse-button-down" and "mouse-button-up"
event handlers of the widget.
Accepted
type values are
AG_ACTION_ON_BUTTONDOWN and
AG_ACTION_ON_BUTTONUP. button is the pressed button index (see
AG_MouseButton(3)). x and
y is the position of the cursor in the widget's coordinate system.

AG_ExecKeyAction() executes any action associated with keyboard events.
It is typically invoked from the "key-down" and "key-up"
event handlers of the widget.
Accepted
type values are
AG_ACTION_ON_KEYDOWN and
AG_ACTION_ON_KEYUP. sym and
mod specify the key index and modifier state (see
AG_KeySym(3) and
AG_KeyMod(3)).

AG_ExecAction() executes the specified action.
AG_ExecAction() is rarely used directly, but it is invoked internally by the
AG_ExecFooAction() functions.

Widget size has changed and
USE_OPENGL is set (and the
GL_PROJECTION or
GL_MODELVIEW matrices may need to be updated).

widget-overlay (void)

Invoked following the
draw() operation; requires
USE_OPENGL.

widget-underlay (void)

Invoked prior to the
draw() operation; requires
USE_OPENGL.

palette-changed (void)

At least one entry in the color palette of the widget has changed.

font-changed (void)

The active font family or font attributes have changed.
The new font may be accessed either via the
font structure member, or using the
AGWIDGET_FONT macro.

The following events are usually generated by input devices:

mouse-motion (int x, int y, int xRel, int yRel, int buttons)

The widget is receiving mouse motion events, and the cursor has been moved.
x and
y are the coordinates of the cursor in the widget's local coordinate system
(these coordinates may be negative or exceed the widget's dimensions if the
cursor is not in the widget's area).
xRel and
yRel represent the displacement relative to the last position of the mouse cursor.
The
buttons argument is a bitmask representing the state of mouse buttons (see
AG_MouseButton(3)).

mouse-button-up (int button, int x, int y)

The widget is receiving mouse button release events, and
button has been released.
x and
y are the cursor coordinates in the widget's local coordinate system.

mouse-button-down (int button, int x, int y)

The widget is receiving mouse button events, and
button has been pressed.
x and
y are the cursor coordinates in the widget's local coordinate system.

mouse-over (void)

The cursor has entered or is leaving the widget's allocated area and the
AG_WIDGET_USE_MOUSEOVER option is set.

key-down (int key, int mod, Ulong ch)

The widget is receiving keyboard events and
key has been pressed.
mod is a bitmask representing the state of the current key modifiers.
If non-zero,
ch is the matching UCS-4 (or ASCII) character.

key-up (int key, int mod, Ulong ch)

The widget is receiving keyboard events and
key has been released.
mod is a bitmask representing the state of the current key modifiers.
If non-zero,
ch is the matching UCS-4 (or ASCII) character.

STRUCTURE DATA

Location of the upper-left pixel (relative to the parent widget).
Read-only (set by container).

int w, h

Size in pixels.
Read-only (set by container).

AG_Rect r

Cached rectangle at 0,0.
Read-only.

AG_Rect2 rView

Cached position & size in display coordinates.
Read-only with one exception: before calling
AG_WidgetDraw(3) to render a child widget, a container widget may temporarily override its
rView in order to render it at a given offset.

AG_Rect2 rSens

Rectangle of sensitivity to mouse events (in display coordinates).
Scrolling containers such as
AG_Scrollview(3) may adjust this rectangle for partially-visible widgets along its edges.

AG_WidgetPalette pal

Color palette: a 4 x 8 (or
AG_WIDGET_NSTATES by
AG_WIDGET_NCOLORS) array of
AG_Color(3). Entries are set by the current
AG_StyleSheet(3). Read-only (use
AG_SetStyle() to change) with one exception: before calling
AG_WidgetDraw(3) to render a child widget, a container widget may temporarily override and
restore its palette entries.

AG_Font *font

Current font associated with the widget (see
AG_Font(3)). Read-only (use
AG_SetStyle() or
AG_SetFont() to change).

Allow
draw(), size_request() and
size_allocate() to use
AG_TextRender(3) and
AG_TextSize(3). Agar will automatically save/restore the font engine state according to the
widget's computed style settings.
Enables reception of the "font-changed" event.

AG_WIDGET_USE_OPENGL

Establish a separate OpenGL context for the widget.
Before the
draw() routine is invoked, Agar will automatically save/restore the
GL_PROJECTION, GL_MODELVIEW and
GL_TEXTURE matrices along with GL attributes
GL_TRANSFORM_BIT, GL_VIEWPORT_BIT and
GL_TEXTURE_BIT. Enables reception of "widget-reshape", "widget-overlay" and "widget-underlay"
events.

SEE ALSO

HISTORY

The
AG_Widget interface first appeared in
Agar 1.0.
Widget-level variable bindings have been replaced by generic
AG_Variable(3) pointers in
Agar 1.3.
Actions were introduced in
Agar 1.4.
AG_WIDGET_USE_OPENGL first appeared in
Agar 1.5, replacing
AG_GLView(3). The
actions, pal and
rSens structure members were made public in
Agar 1.6.0.
Agar 1.6.0 also added
AG_SetStyleF(), AG_PushBlendingMode(), AG_PopBlendingMode(), and introduced the "font-changed" and "palette-changed" events.