Note: The Agar manual pages follow certain conventions, notably concerning function return values. Please read AG_Intro(3) first.
SYNOPSIS
#include <agar/core.h> #include <agar/gui.h> |
DESCRIPTION
|
An Agar graphical user interface is described as a tree of widgets
(i.e., structures derived from
AG_Widget. A widget object is always attached (via AG_ObjectAttach(3)) to a parent container widget. Some container widgets (such as AG_Box(3) or AG_Window(3)) are designed as general-purpose container widgets. Other widgets (such as AG_FileDlg(3)) will internally create, attach and position a specific set of child widgets to create a complex, easily re-usable dialog (Agar developers are encouraged to create custom widgets using this technique). The AG_Widget structure is derived from AG_Object(3). Using Agar's Object system, custom widgets are easily implemented (or derived from existing widget classes) as part of user applications. Agar widgets are extensively re-used. The Object system also provides the AG_Event(3) system and the AG_Variable(3) interface which is the basis of widget bindings (see BINDINGS section below). |
INHERITANCE HIERARCHY
| AG_Object(3)-> AG_Widget. |
CLASS OPERATIONS
Object operations specific to the
AG_Widget class are defined as follows:
typedef struct ag_widget_class {
struct ag_object_class _inherit;
void (*draw)(AG_Widget *w);
void (*size_request)(AG_Widget *w, AG_SizeReq *req);
int (*size_allocate)(AG_Widget *w, const AG_SizeAlloc *alloc);
} AG_WidgetClass;
The draw() operation renders the widget to the display. Throughout the documentation, the draw() operation is referred to as the rendering context, and some functions (such as AG_WidgetBlitSurface()) are not safe to invoke in any other context. The size_request() option queries the widget for an initial, preferred geometry, without any guarantee that the request will be satisfied. For example, a AG_Label(3) widget might return the expected size in pixels of the rendered label's text. The size_allocate() function is called whenever the widget has been allocated a new size or position within its parent container. The AG_SizeAlloc parameter specifies the new allocation. It is also safe to assume that when size_allocate is invoked, the w, h, x, y members of the AG_Widget structure are already set to the new allocated position and size. The size_allocate() routine of a container widget is responsible for positioning and dimensioning of child widgets attached to it (by calling AG_WidgetSizeAlloc() on them -- see WIDGET SIZING section below). The function should return 0 on success or -1 to flag the widget as "undersize", disabling further calls to draw(). |
WIDGET SIZING
|
The AG_Expand() function arranges for the widget to expand, filling all available area in its parent container widget. AG_ExpandHoriz() and AG_ExpandVert() cause the widget to expand to fill available space horizontally or vertically. Note that most widget constructors recognize AG_FOO_EXPAND, AG_FOO_HFILL and AG_FOO_VFILL option flags. Setting these flags is equivalent to calling AG_Expand(), AG_ExpandHoriz() and AG_ExpandVert(), respectively. The AG_WidgetSizeReq() function 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. 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). The AG_SizeReq and AG_SizeAlloc structures are defined as follows: typedef struct ag_size_req {
int w, h; /* Requested geometry in pixels */
} AG_SizeReq;
typedef struct ag_size_alloc {
int w, h; /* Allocated geometry in pixels */
int x, y; /* Allocated position in pixels */
} AG_SizeAlloc;
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. |
INPUT STATE
FOCUS STATE
The focus state of widgets enables the reception of specific types of
events which are filtered by default.
The focus state also affects the behavior and appearance of some widgets.
A widget holding focus (in a currently focused window) will receive mouse
events
mouse-motion(), mouse-button-up(), as well as keyboard events
key-up() and
key-down() (note that unfocused widgets can be configured to receive those events
unfiltered as well using the
AG_WIDGET_UNFOCUSED_* options).
AG_WidgetSetFocusable() specifies whether the widget should be allowed to receive focus (1 = accept focus, 0 = reject focus). The default is to reject focus. Further AG_WidgetFocus() calls on a widget rejecting focus will return 0. The AG_WidgetFocus() function gives focus to the given widget (and all of its parent widgets, up to the parent window if there is one). AG_WidgetFocus() returns 1 on success and 0 if the widget cannot gain focus (i.e., AG_WIDGET_FOCUSABLE is not set). If the widget is already focused, the function is a no-op and returns 1. AG_WidgetUnfocus() removes the focus state from the given widget and its children (but not the parent window if any). AG_WidgetIsFocused() returns 1 if the widget is currently holding focus (i.e., the widget has the focus flag set, and its parent window, if any, is focused as well). AG_WidgetIsFocusedInWindow() returns 1 if the widget has the focus flag set (without evaluating the focus state of any parent windows). With both functions, the AG_View(3) VFS as well as the AG_Widget object must be locked when the call is made. AG_WidgetForwardFocus() arranges automatic forwarding of the focus to a specified widget. Whenever AG_WidgetFocus will be invoked on widget, the focus will be given to widgetToFocus instead. |
COORDINATES
The AG_WidgetArea() routine tests whether view coordinates x and y lie inside of the widget's allocated space. The AG_WidgetRelativeArea() variant accepts widget coordinates. |
BLITTING SURFACES
These functions manage blitting of graphical surfaces.
They are designed specifically for use in GUI widgets.
The
AG_WidgetBlit*() routines must all be invoked from rendering context (i.e., the
draw operation of widgets), and may not be used in any other context.
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)). Under multithreading, AG_WidgetMapSurface() may be invoked from any context, but the returned name is only valid as long as the widget is locked (see AG_ObjectLock(3)). 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_WidgetBlitFrom() function renders a previously mapped (possibly hardware) surface from the source widget srcWidget (using source rectangle rs) onto the destination widget dstWidget, at coordinates x, y. This function must be invoked in rendering context. The AG_WidgetBlitSurface() variant invokes AG_WidgetBlitFrom with the same argument for both srcWidget and dstWidget (and rs set to NULL). |
RENDERING AND PRIMITIVES
|
These routines are provided for use in GUI widgets, exclusively in the context
of the widget
draw operation.
A number of simple primitive drawing routines are also available via the AG_WidgetPrimitives(3) interface.
The AG_PushClipRect() function pushes a rectangle onto the stack of clipping rectangles. AG_PopClipRect() pops the last entry from the clipping rectangle stack. The clipping rectangle is given in coordinates relative to the widget. These routines must be invoked from GUI rendering context. The method of clipping depends on the underlying graphics API. For instance, SDL drivers use SDL_SetClipRect(3) and OpenGL drivers use glClipPlane(3). In either case, the actual clipping rectangle passed to the graphics API is the intersection of all clipping rectangles on the stack. |
BINDINGS
|
Agar widgets can be configured to directly access data of specific types.
For example,
AG_Slider(3) provides a binding called
value, which (in the current implementation) supports the standard integer and
floating-point types.
Connecting
value to an integer or floating point variable allows the user to directly set the
value of the variable with the need for tedious callback routines.
Similarly,
AG_Textbox(3) connects to a text buffer.
It is also possible to configure
function bindings such that the value is evaluated from a provided function every time
the variable is retrieved.
Widget bindings are established using the AG_BindFoo(), AG_BindFooFn() and AG_BindFooMp() functions, see AG_Variable(3) for more information. Bindings are specifically documented in the API reference. Manual pages for standard Agar widgets include a BINDINGS section with a list of bindings supported by each widget, their supported data types and effects. Since the value of bindings associated with a widget often dictates the way the widget is rendered (e.g., AG_Button(3) is drawn as a pressed button if its state binding is 1), Agar provides a built-in facility to monitor binding values and request a video update whenever the value changes: |
WIDGET REDRAW CONTROL
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 (i.e., from the draw() operation of a widget), 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. |
WIDGET QUERIES
AG_ParentWindow() returns a pointer to the parent AG_Window(3) for the given widget. If the widget is unattached, NULL is returned. The AG_View(3) VFS must be locked when the call is made. The AG_WidgetFind() function searches for a given widget by name, given an absolute path, and returns a pointer to the widget, or NULL. AG_WidgetFind() works differently from the generic AG_ObjectFind(3) function, in that widgets not effectively attached to the AG_View(3) may be included in the search (for example, widgets attached to AG_Notebook(3) tabs). AG_WidgetFindFocused() recursively searches win for a widget holding focus. Where multiple widgets may be holding focus, widgets found deepest in the tree have priority over their parents. AG_WidgetFindFocused() returns NULL if no widget is focused. AG_WidgetFindPoint() searches for a widget matching the given class mask enclosing the point specified in display (pixel) coordinates. The AG_WidgetFindRect() variant requires that the widget enclose the specified rectangle. Under multithreading, the return value of AG_WidgetFind*(), should be considered valid only as long as the AG_View(3) VFS remains locked. |
WIDGET RENDERING
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(). AG_WidgetHide() and AG_WidgetShow() set the visibility of a widget. AG_WidgetVisible() returns 1 if the widget is visible, 0 if hidden. The AG_WidgetSurface() routine renders the widget to a newly-allocated AG_Surface(3). This surface should be freed after use. AG_SetStyle() changes the style (theme) associated with a widget. See AG_Style(3) for more information about widget themes. Note that child widgets automatically inherit the theme associated with their parent object. |
WIDGET ACTIONS
Input events such as key presses or mouse button events can be "tied" to
simple actions, such as executing a specified routine or controlling a flag
variable.
Widget actions are preferred over event handlers where the conditions are fixed
(e.g., a specific mouse button was clicked, or a specific key was pressed).
Keyboard and mouse bindings may be edited by the user.
Actions are identified by a name string, and are mapped to events by a table
kept in the
AG_Widget structure.
The
AG_MenuWidgetActions(3) function of
AG_Menu(3) creates a generic menu item containing a widget's available 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. Actions are tied to events (identified by event string) with AG_ActionOn*(). 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). AG_ExecMouseAction() executes any action associated with mouse button events. 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. 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. |
EVENTS
The GUI system may send
AG_Widget objects the following events:
The following events are usually generated by input devices:
|
STRUCTURE DATA
For the
AG_Widget object:
|
FLAGS
The
flags member of the
AG_Widget structure accepts the following flags:
|
SEE ALSO
| AG_Cursor(3), AG_KeySym(3), AG_KeyMod(3), AG_GlobalKeys(3), AG_Rect(3), AG_Style(3), AG_Surface(3), AG_Variable(3), AG_View(3), AG_WidgetPrimitives(3), AG_Window(3) |
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.4. The widget "actions" interface first appeared in Agar 1.4. |
