.\" Copyright (c) 2002-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 August 20, 2002
.Dt AG_WIDGET 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.0
.Sh NAME
.Nm AG_Widget
.Nd agar widget framework
.Sh SYNOPSIS
.Bd -literal
#include
#include
.Ed
.Sh DESCRIPTION
An Agar graphical user interface is described as a tree of objects
(see
.Xr AG_Object 3 )
derived from the
.Nm
class.
.Pp
The Widget tree describes the parent/child relation between widgets.
This relation has implications in the way geometry will be allocated to
widgets (see
.Dq WIDGET SIZING
for details).
.Pp
The Agar GUI library is open, such that new, custom widgets may be easily
implemented (or derived from existing widget classes) as part of user
applications.
Agar widgets are extensively re-used.
.Pp
Widgets use
.Xr AG_Event 3
(a part of the
.Xr AG_Object 3
system) to generate and handle many types of events.
.Pp
The
.Xr AG_Variable 3
interface is also critical to the Agar GUI system.
It is customary to use the
.Fn AG_BindFoo
and
.Fn AG_BindFooFn
functions of
.Xr AG_Variable 3
to connect some data (e.g., an integer or floating-point variable) to some
.Em state
provided by the widget (e.g.,
.Xr AG_Slider 3
provides
.Sq value ,
.Sq min
and
.Sq max
states).
In the context of Agar-GUI, we refer to these connections as
.Sq bindings .
See
.Xr AG_Variable 3
for more information.
Manual pages for all standard Agar widgets all include an
.Dq BINDINGS
section with a list of bindings supported by each widget, their supported
data types and effects.
.Sh INHERITANCE HIERARCHY
.Xr AG_Object 3 ->
.Nm .
.Sh CLASS OPERATIONS
Object operations specific to the
.Nm
class are defined as follows:
.Bd -literal
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;
.Ed
.Pp
The
.Fn draw
operation renders the widget to the display.
Throughout the documentation, the
.Fn draw
operation is referred to as the
.Sq rendering context ,
and some functions (such as
.Fn AG_WidgetBlitSurface )
are not safe to invoke in any other context.
.Pp
The
.Fn size_request
option queries the widget for an initial, preferred geometry, without any
guarantee that the request will be satisfied.
For example, a
.Xr AG_Label 3
widget might return the expected size in pixels of the rendered label's text.
.Pp
The
.Fn size_allocate
callback notifies the widget that it has been allocated a new size or position
within its parent.
The
.Ft AG_SizeAlloc
parameter specifies the new allocation.
It is also safe to assume that when
.Fa size_allocate
is invoked, the
.Va w ,
.Va h ,
.Va x ,
.Va y
members of the
.Nm
structure are already set to the new allocated position and size.
.Pp
Widgets are not allowed to modify their geometry from
.Fn size_allocate ,
but operation can return -1 to reject the allocated geometry.
This sets the
.Dv AG_WIDGET_UNDERSIZE
flag, disabling rendering of the widget with its current geometry.
.Sh WIDGET SIZING
.nr nS 1
.Ft "void"
.Fn AG_Expand "AG_Widget *widget"
.Pp
.Ft "void"
.Fn AG_ExpandHoriz "AG_Widget *widget"
.Pp
.Ft "void"
.Fn AG_ExpandVert "AG_Widget *widget"
.Pp
.Ft "void"
.Fn AG_WidgetSizeReq "AG_Widget *widget" "AG_SizeReq *req"
.Pp
.Ft "int"
.Fn AG_WidgetSizeAlloc "AG_Widget *widget" "AG_SizeAlloc *alloc"
.Pp
.Ft void
.Fn AG_WidgetSetPosition "AG_Widget *widget" "int x" "int y"
.Pp
.Ft void
.Fn AG_WidgetSetSize "AG_Widget *widget" "int w" "int h"
.Pp
.Ft void
.Fn AG_WidgetSetGeometry "AG_Widget *widget" "AG_Rect rect"
.Pp
.nr nS 0
The
.Fn AG_Expand
function arranges for the widget to expand, filling all available area
in its parent container widget.
.Fn AG_ExpandHoriz
and
.Fn AG_ExpandVert
cause the widget to expand to fill available space horizontally or vertically.
.Pp
The
.Fn AG_WidgetSizeReq
function invokes the
.Fn size_request
operation of the widget and returns its size requisition into
.Fa req .
.Fn AG_WidgetSizeAlloc
allocates the given position and geometry of the widget.
These functions are generally used to implement
.Sq container
widgets.
The
.Ft AG_SizeReq
and
.Ft AG_SizeAlloc
structures are defined as follows:
.Bd -literal
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;
.Ed
.Pp
.Fn AG_WidgetSetPosition
sets the effective position of the widget relative to its parent container.
.Fn AG_WidgetSetSize
sets the size of the widget in pixels.
.Fn AG_WidgetSetGeometry
sets both position and size of a widget from the specified
.Ft AG_Rect .
These functions are typically only used in the context of the
.Fn size_request
and
.Fn size_allocate
routines of container widgets.
.Sh INPUT STATE
.nr nS 1
.Ft "void"
.Fn AG_WidgetEnable "AG_Widget *widget"
.Pp
.Ft "void"
.Fn AG_WidgetDisable "AG_Widget *widget"
.Pp
.Ft "int"
.Fn AG_WidgetEnabled "AG_Widget *widget"
.Pp
.Ft "int"
.Fn AG_WidgetDisabled "AG_Widget *widget"
.Pp
.nr nS 0
The "enabled" flag of a widget determines whether the user is allowed to modify
whatever data the widget is accessing.
The interpretation of this flag is widget-specific.
.Fn AG_WidgetEnable
sets the flag,
.Fn AG_WidgetDisable
clears it.
.Sh FOCUS STATE
.nr nS 1
.Ft "void"
.Fn AG_WidgetSetFocusable "AG_Widget *widget" "int enable"
.Pp
.Ft "void"
.Fn AG_WidgetFocus "AG_Widget *widget"
.Pp
.Ft "void"
.Fn AG_WidgetUnfocus "AG_Widget *widget"
.Pp
.Ft "int"
.Fn AG_WidgetFocused "AG_Widget *widget"
.Pp
.Ft "AG_Widget *"
.Fn AG_WidgetFindFocused "AG_Window *win"
.Pp
.nr nS 0
The focus state of a widget controls both its appearance and enables the
reception of specific types of events which are filtered by default.
A focused widget (in a currently focused window) will receive mouse events
.Sq window-mousemotion ,
.Sq window-mousebuttonup ,
as well as keyboard events
.Sq window-keyup
and
.Sq window-keydown .
.Pp
Widget can explicitely disable focus-dependent filtering for those events
by setting the flags
.Dv AG_WIDGET_UNFOCUSED_MOTION ,
.Dv AG_WIDGET_UNFOCUSED_BUTTONUP
and
.Dv AG_WIDGET_UNFOCUSED_BUTTONDOWN .
.Pp
.Fn AG_WidgetSetFocusable
specifies whether the widget should be allowed to receive focus
(default = FALSE).
.Pp
The
.Fn AG_WidgetFocus
function moves the keyboard/mousemotion focus over the given widget
and its parents.
.Fn AG_WidgetUnfocus
removes the focus state from the given widget and its children.
.Pp
.Fn AG_WidgetFocused
returns 1 if
.Fa widget
is currently holding focus.
.Pp
.Fn AG_WidgetFindFocused
recursively searches
.Fa win
for a widget holding focus.
Where multiple widgets may be holding focus, widgets found deepest in the
tree have priority over their parents.
.Fn AG_WidgetFindFocused
returns NULL if no widget is focused.
Note: Under multithreading, the return value is only valid as long as the
.Xr AG_View 3
VFS object is locked.
.Sh COORDINATES
.nr nS 1
.Ft int
.Fn AG_WidgetArea "AG_Widget *widget" "int x" "int y"
.Pp
.Ft int
.Fn AG_WidgetRelativeArea "AG_Widget *widget" "int x" "int y"
.Pp
.nr nS 0
The
.Fn AG_WidgetArea
routine tests whether view coordinates
.Fa x
and
.Fa y
lie inside of the widget's allocated space.
The
.Fn AG_WidgetRelativeArea
variant accepts widget coordinates.
.Sh BLITTING SURFACES
These functions manage blitting of graphical surfaces.
They are designed specifically for use in GUI widgets.
The
.Fn AG_WidgetBlit*
routines must all be invoked from rendering context (i.e., the
.Fa draw
operation of widgets), and may not be used in any other context.
.Pp
.nr nS 1
.Ft void
.Fn AG_WidgetBlit "AG_Widget *widget" "AG_Surface *src" "int x" "int y"
.Pp
.Ft int
.Fn AG_WidgetMapSurface "AG_Widget *widget" "AG_Surface *su"
.Pp
.Ft int
.Fn AG_WidgetMapSurfaceNODUP "AG_Widget *widget" "AG_Surface *su"
.Pp
.Ft void
.Fn AG_WidgetReplaceSurface "AG_Widget *widget" "int surface_id" "AG_Surface *newSurface"
.Pp
.Ft void
.Fn AG_WidgetReplaceSurfaceNODUP "AG_Widget *widget" "int surface_id" "AG_Surface *newSurface"
.Pp
.Ft void
.Fn AG_WidgetUnmapSurface "AG_Widget *widget" "int surface_id"
.Pp
.Ft void
.Fn AG_WidgetUpdateSurface "AG_Widget *widget" "int surface_id"
.Pp
.Ft void
.Fn AG_WidgetBlitFrom "AG_Widget *dstWidget" "AG_Widget *srcWidget" "int surface_id" "AG_Rect *rs" "int x" "int y"
.Pp
.Ft void
.Fn AG_WidgetBlitSurface "AG_Widget *widget" "int surface_id" "int x" "int y"
.Pp
.nr nS 0
The
.Fn AG_WidgetBlit
function performs a software->hardware blit from the surface
.Fa src
to the video display at the given widget coordinates.
.Fn AG_WidgetBlit
must invoked in rendering context.
See
.Xr AG_Surface 3
for more information on the Agar surface structure.
.Pp
Software to hardware blits are slow, so the
.Fn AG_WidgetMapSurface
interface provides a way to take advantage of hardware->hardware blits.
It copies the specified surface (possibly creating a hardware texture if
Agar is using an API such as OpenGL), and returns a name which will be
used to later reference the surface.
.Pp
The
.Fn AG_WidgetMapSurfaceNODUP
variant does not copy the given surface, which is assumed to remain valid
for as long as the widget exists.
.Pp
Under multithreading,
.Fn AG_WidgetMapSurface
may be invoked from any context, but the returned name is only valid as
long as the widget is locked (see
.Xr AG_ObjectLock 3 ) .
.Pp
.Fn AG_WidgetReplaceSurface
replaces the contents of a previously-mapped surface with the contents of
.Fa newSurface .
The
.Fn AG_WidgetReplaceSurfaceNODUP
variant avoids duplicating the surface.
.Pp
.Fn AG_WidgetUnmapSurface
destroys the given surface mapping.
It is equivalent to invoking
.Fn AG_WidgetReplaceSurface
with a NULL surface.
The function is safe to use from any context.
.Pp
It is important to note that in OpenGL mode,
.Fn AG_WidgetReplaceSurface
and
.Fn 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.
.Pp
The
.Fn 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).
.Pp
The
.Fn AG_WidgetBlitFrom
function renders a previously mapped (possibly hardware) surface from the
source widget
.Fa srcWidget
(using source rectangle
.Fa rs )
onto the destination widget
.Fa dstWidget ,
at coordinates
.Fa x ,
.Fa y .
This function must be invoked in rendering context.
.Pp
The
.Fn AG_WidgetBlitSurface
variant invokes
.Fa AG_WidgetBlitFrom
with the same argument for both
.Fa srcWidget
and
.Fa dstWidget
(and
.Fa rs
set to NULL).
.Sh RENDERING AND PRIMITIVES
These routines are provided for use in GUI widgets, exclusively in the context
of the
.Nm
.Fa draw
operation.
.Pp
.nr nS 1
.Ft void
.Fn AG_PushClipRect "AG_Widget *widget" "AG_Rect r"
.Pp
.Ft void
.Fn AG_PopClipRect "void"
.Pp
.Ft void
.Fn AG_WidgetPushCursor "AG_Widget *widget" "int cursor"
.Pp
.Ft void
.Fn AG_WidgetPopCursor "AG_Widget *widget"
.Pp
.Ft void
.Fn AG_WidgetPutPixel32 "AG_Widget *widget" "int x" "int y" "Uint32 pixel"
.Pp
.Ft void
.Fn AG_WidgetPutPixelRGB "AG_Widget *widget" "int x" "int y" "Uint8 red" "Uint8 green" "Uint8 blue"
.Pp
.Ft void
.Fn AG_WidgetBlendPixelRGBA "AG_Widget *widget" "int x" "int y" "Uint8 color[4]" "AG_BlendFn blendFn"
.Pp
.Ft void
.Fn AG_WidgetBlendPixel32 "AG_Widget *widget" "int x" "int y" "Uint32 pixel" "AG_BlendFn blendFn"
.Pp
.nr nS 0
.Pp
The
.Fn AG_PushClipRect
function pushes a rectangle onto the stack of clipping rectangles.
.Fn AG_PopClipRect
pops the last entry from the clipping rectangle stack.
The clipping rectangle is given in coordinates relative to the widget.
.Pp
These routines must be invoked from GUI rendering context.
The method of clipping depends on the underlying graphics API.
For instance, in SDL mode, the temporary rectangle is set by
.Xr SDL_SetClipRect 3
and
.Xr glClipPlane 3
is used in OpenGL mode.
In either case, the actual clipping rectangle passed to the graphics API
is the intersection of all clipping rectangles on the stack.
.Pp
The
.Fn AG_WidgetPushCursor
function changes the active cursor, saving the previous one.
The argument is an index into the global
.Va agCursors
array.
The
.Fn AG_WidgetPopCursor
restores the previously saved cursor.
.Pp
.Fn AG_WidgetPutPixel32
function writes a pixel (given in
.Va agVideoFmt
format) to the specified widget coordinates.
The
.Fn AG_WidgetPutPixelRGB
variant accepts 8-bit component values.
.Pp
The
.Fn AG_WidgetBlendPixelRGBA
and
.Fn AG_WidgetBlendPixel32
routines blend the specified color against the current pixel at widget
coordinates
.Fa x ,
.Fa y .
.Fa color
specifies the source 8-bit RGBA components.
Pixels are blended according to the given function
.Fn blendFn ,
which may be one of:
.Bd -literal
typedef enum ag_blend_func {
AG_ALPHA_OVERLAY, /* dA = sA+dA (emulated in GL mode) */
AG_ALPHA_SRC, /* dA = sA */
AG_ALPHA_DST, /* dA = dA */
AG_ALPHA_ONE_MINUS_DST, /* dA = 1-dA */
AG_ALPHA_ONE_MINUS_SRC /* dA = 1-sA */
} AG_BlendFn;
.Ed
.Pp
The display surface must be locked (see
.Xr AG_LockView 3
and
.Xr AG_UnlockView 3 )
before any of the
.Fn AG_WidgetPutPixel*
and
.Fn AG_WidgetBlendPixel*
routines are invoked.
Put-pixel and blend-pixel operations are also subject to the current clipping
rectangle (as set by
.Fn AG_PushClipRect ) .
.Pp
.Fn AG_WidgetPutPixel*
and
.Fn AG_WidgetBlendPixel*
differ from the low-level
.Fn AG_VIEW_PUT_PIXEL*
operations of
.Xr AG_View 3
in that the coordinates are relative to the widget's coordinate system.
These operations are also emulated if the display is not framebuffer-based.
.Sh GRAPHICS PRIMITIVES
These primitives are designed specifically for use in GUI widgets.
They must be called from the
.Fa draw
functions of widgets exclusively and may not be used in any other context.
.Pp
The coordinates for all of the
.Fn AG_Draw*
functions are given in pixels and are relative to the specified widget.
Unless otherwise noted, the
.Fa c
arguments are indices into the global GUI color array (see
.Xr AG_Colors 3 ).
.Pp
.nr nS 1
.Ft void
.Fn AG_DrawPixel "AG_Widget *widget" "int x" "int y" "Uint32 pixel"
.Pp
.Ft void
.Fn AG_DrawPixelBlended "AG_Widget *widget" "int x" "int y" "Uint32 pixel" "AG_BlendFn blendFn"
.Pp
.Ft void
.Fn AG_DrawPixelRGB "AG_Widget *widget" "int x" "int y" "Uint8 r" "Uint8 g" "Uint8 b"
.Pp
.Ft void
.Fn AG_DrawBox "AG_Widget *widget" "AG_Rect r" "int z" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawBoxDisabled "AG_Widget *widget" "AG_Rect r" "int z" "Uint32 c1" "Uint32 c2"
.Pp
.Ft void
.Fn AG_DrawBoxRounded "AG_Widget *widget" "AG_Rect r" "int z" "int radius" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawBoxRoundedTop "AG_Widget *widget" "AG_Rect r" "int z" "int radius" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawFrame "AG_Widget *widget" "AG_Rect r" "int z" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawFrameBlended "AG_Widget *widget" "AG_Rect r" "Uint8 c[4]" "AG_BlendFn blendFn"
.Pp
.Ft void
.Fn AG_DrawCircle "AG_Widget *widget" "int x" "int y" "int radius" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawCircle2 "AG_Widget *widget" "int x" "int y" "int radius" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawLine "AG_Widget *widget" "int x1" "int y1" "int x2" "int y2" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawLine2 "AG_Widget *widget" "int x1" "int y1" "int x2" "int y2" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawLineH "AG_Widget *widget" "int x1" "int x2" "int y" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawLineV "AG_Widget *widget" "int x" "int y1" "int y2" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawRectOutline "AG_Widget *widget, AG_Rect r" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawRectFilled "AG_Widget *widget, AG_Rect r" "Uint32 c"
.Pp
.Ft void
.Fn AG_DrawPlus "AG_Widget *widget, AG_Rect r" "Uint8 c[4]" "AG_BlendFn blendFn"
.Pp
.Ft void
.Fn AG_DrawMinus "AG_Widget *widget, AG_Rect r" "Uint8 c[4]" "AG_BlendFn blendFn"
.Pp
.Ft void
.Fn AG_DrawTiling "AG_Widget *widget, AG_Rect r" "int tileSz" "int offset" "Uint32 c1" "Uint32 c2"
.Pp
.Ft void
.Fn AG_DrawArrowUp "AG_Widget *widget" "int x" "int y" "int h" "Uint32 c1" "Uint32 c2"
.Pp
.Ft void
.Fn AG_DrawArrowDown "AG_Widget *widget" "int x" "int y" "int h" "Uint32 c1" "Uint32 c2"
.Pp
.Ft void
.Fn AG_DrawArrowLeft "AG_Widget *widget" "int x" "int y" "int w" "Uint32 c1" "Uint32 c2"
.Pp
.Ft void
.Fn AG_DrawArrowRight "AG_Widget *widget" "int x" "int y" "int w" "Uint32 c1" "Uint32 c2"
.Pp
.nr nS 0
For all of the following functions accepting
.Ft Uint32
color arguments, the values are assumed to be in
.Fa agViewFmt
pixel format.
.Pp
.Fn AG_DrawPixel
draws a single pixel at the specified coordinates.
The
.Fn AG_DrawPixelBlended
variant performs alpha-blending using the specified blending function
(see
.Fn AG_WidgetBlendPixelRGBA ) .
The
.Fn AG_DrawPixelRGB
variant accepts RGB component arguments.
.Pp
.Fn AG_DrawBox
draws a 3D-style box, where
.Fa z
indicates the
.Sq depth
in pixels.
The
.Fn AG_DrawBoxDisabled
variant uses a stipple pattern of
.Fa c1
against
.Fa c2 ,
traditionally used to indicate a "disabled" control.
.Pp
.Fn AG_DrawBoxRounded
renders a box with the edges rounded to the given
.Fa radius .
The
.Fn AG_DrawBoxRoundedTop
variant only rounds the top two corners.
.Pp
.Fn AG_DrawFrame
draws a 3D-style frame.
.Fn AG_DrawFrameBlended
draws a frame with alpha-blending.
.Pp
.Fn AG_DrawCircle
draws a circle with the origin at
.Fa x ,
.Fa y
and a radius of
.Fa radius
pixels.
.Pp
.Fn AG_DrawLine
scan-converts a line segment going from point
.Fa x1 ,
.Fa y1
to point
.Fa x2 ,
.Fa y2 .
The variants
.Fn AG_DrawLineH
and
.Fn AG_DrawLineV
render horizontal and vertical line segments, respectively.
.Fn AG_DrawLine2
renders two line segments for a 3D-style effect.
.Pp
.Fn AG_DrawRectOutline
draws the outline of a rectangle.
.Pp
.Fn AG_DrawRectFilled
fills a rectangle of pixels.
.Pp
.Fn AG_DrawPlus
and
.Fn AG_DrawMinus
draw plus ("+") or minus ("-") signs spanning
.Fa r ,
using the specified color and blending function.
.Pp
.Fn AG_DrawTiling
fills
.Fa r
with a two-color tiling pattern.
.Fa tileSz
is the size of the tiles in pixels,
.Fa offset
is an offset in pixels and
.Fa c1 ,
.Fa c2
specify the colors of the tiles.
.Pp
.Fn AG_DrawArrowUp ,
.Fn AG_DrawArrowDown ,
.Fn AG_DrawArrowLeft
and
.Fn AG_DrawArrowRight
draw an arrow at the specified coordinates.
.Fa h
and
.Fa w
specify the height/width of the arrow in pixels.
.Sh BINDINGS
Agar widgets can be configured to directly access data of specific types.
For example,
.Xr AG_Slider 3
provides a binding called
.Sq value ,
which (in the current implementation) supports the standard integer and
floating-point types.
Connecting
.Sq 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,
.Xr AG_Textbox 3
connects to a text buffer.
It is also possible to configure
.Sq function
bindings such that the value is evaluated from a provided function every time
the variable is retrieved.
.Pp
NOTE: This interface is now
.Em deprecated
and the more generic
.Xr AG_Variable 3
interface should be used instead.
.nr nS 1
.Ft "AG_WidgetBinding *"
.Fn AG_WidgetBind "AG_Widget *widget, const char *binding" "enum ag_variable_type type, ..."
.Pp
.Ft "AG_WidgetBinding *"
.Fn AG_WidgetGetBinding "AG_Widget *widget" "const char *binding" "void *res"
.Pp
.Ft "int"
.Fn AG_WidgetCopyBinding "AG_Widget *dst_widget" "const char *dst_binding" "AG_WidgetBinding *src_binding"
.Pp
.Ft void
.Fn AG_WidgetLockBinding "AG_WidgetBinding *binding"
.Pp
.Ft void
.Fn AG_WidgetUnlockBinding "AG_WidgetBinding *binding"
.Pp
.Ft "void"
.Fn AG_WidgetBindBool "AG_Widget *widget" "const char *binding" "int *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindInt "AG_Widget *widget" "const char *binding" "int *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindUint "AG_Widget *widget" "const char *binding" "Uint *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindUint8 "AG_Widget *widget" "const char *binding" "Uint8 *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindSint8 "AG_Widget *widget" "const char *binding" "Sint8 *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindUint16 "AG_Widget *widget" "const char *binding" "Uint16 *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindSint16 "AG_Widget *widget" "const char *binding" "Sint16 *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindUint32 "AG_Widget *widget" "const char *binding" "Uint32 *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindSint32 "AG_Widget *widget" "const char *binding" "Sint32 *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindFloat "AG_Widget *widget" "const char *binding" "float *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindDouble "AG_Widget *widget" "const char *binding" "double *p"
.Pp
.Ft "void"
.Fn AG_WidgetBindPointer "AG_Widget *widget" "const char *binding" "void **p"
.Pp
.Ft "void"
.Fn AG_WidgetBindString "AG_Widget *widget" "const char *binding" "char *p" "size_t len"
.Pp
.Ft "void"
.Fn AG_WidgetBindFlag "AG_Widget *widget" "const char *binding" "int *p" "int bitmask"
.Pp
.Ft "void"
.Fn AG_WidgetBindFlag8 "AG_Widget *widget" "const char *binding" "Uint8 *p" "Uint8 bitmask"
.Pp
.Ft "void"
.Fn AG_WidgetBindFlag16 "AG_Widget *widget" "const char *binding" "Uint16 *p" "Uint16 bitmask"
.Pp
.Ft "void"
.Fn AG_WidgetBindFlag32 "AG_Widget *widget" "const char *binding" "Uint32 *p" "Uint32 bitmask"
.Pp
.Ft int
.Fn AG_WidgetBool "AG_Widget *widget" "const char *binding"
.Pp
.Ft int
.Fn AG_WidgetInt "AG_Widget *widget" "const char *binding"
.Pp
.Ft "Uint"
.Fn AG_WidgetUint "AG_Widget *widget" "const char *binding"
.Pp
.Ft Uint8
.Fn AG_WidgetUint8 "AG_Widget *widget" "const char *binding"
.Pp
.Ft Sint8
.Fn AG_WidgetSint8 "AG_Widget *widget" "const char *binding"
.Pp
.Ft Uint16
.Fn AG_WidgetUint16 "AG_Widget *widget" "const char *binding"
.Pp
.Ft Sint16
.Fn AG_WidgetSint16 "AG_Widget *widget" "const char *binding"
.Pp
.Ft Uint32
.Fn AG_WidgetUint32 "AG_Widget *widget" "const char *binding"
.Pp
.Ft Sint32
.Fn AG_WidgetSint32 "AG_Widget *widget" "const char *binding"
.Pp
.Ft float
.Fn AG_WidgetFloat "AG_Widget *widget" "const char *binding"
.Pp
.Ft double
.Fn AG_WidgetDouble "AG_Widget *widget" "const char *binding"
.Pp
.Ft "char *"
.Fn AG_WidgetString "AG_Widget *widget" "const char *binding"
.Pp
.Ft size_t
.Fn AG_WidgetCopyString "AG_Widget *widget, const char *binding, char *dst" "size_t dst_size"
.Pp
.Ft void
.Fn AG_WidgetSetBool "AG_Widget *widget" "const char *binding" "int i"
.Pp
.Ft void
.Fn AG_WidgetSetInt "AG_Widget *widget" "const char *binding" "int i"
.Pp
.Ft void
.Fn AG_WidgetSetUint "AG_Widget *widget" "const char *binding" "Uint i"
.Pp
.Ft void
.Fn AG_WidgetSetUint8 "AG_Widget *widget" "const char *binding" "Uint8 u8"
.Pp
.Ft void
.Fn AG_WidgetSetSint8 "AG_Widget *widget" "const char *binding" "Sint8 u8"
.Pp
.Ft void
.Fn AG_WidgetSetUint16 "AG_Widget *widget" "const char *binding" "Uint16 u16"
.Pp
.Ft void
.Fn AG_WidgetSetSint16 "AG_Widget *widget" "const char *binding" "Sint16 u16"
.Pp
.Ft void
.Fn AG_WidgetSetUint32 "AG_Widget *widget" "const char *binding" "Uint32 u32"
.Pp
.Ft void
.Fn AG_WidgetSetSint32 "AG_Widget *widget" "const char *binding" "Sint32 u32"
.Pp
.Ft void
.Fn AG_WidgetSetFloat "AG_Widget *widget" "const char *binding" "float f"
.Pp
.Ft void
.Fn AG_WidgetSetDouble "AG_Widget *widget" "const char *binding" "double d"
.Pp
.Ft void
.Fn AG_WidgetSetString "AG_Widget *widget" "const char *binding" "const char *s"
.Pp
.Ft void
.Fn AG_WidgetSetPointer "AG_Widget *widget" "const char *binding" "void *p"
.Pp
.nr nS 0
The
.Fn AG_WidgetBind
function either overrides or creates a new binding.
It is a
.Em deprecated
interface to the
.Fn AG_BindFoo
routines of
.Xr AG_Variable 3 .
Acceptable values for the
.Fa type
argument include:
.Pp
.Bl -tag -compact
.It AG_WIDGET_NONE
.It AG_WIDGET_BOOL
.It AG_WIDGET_UINT
.It AG_WIDGET_INT
.It AG_WIDGET_UINT8
.It AG_WIDGET_SINT8
.It AG_WIDGET_UINT16
.It AG_WIDGET_SINT16
.It AG_WIDGET_UINT32
.It AG_WIDGET_SINT32
.It AG_WIDGET_FLOAT
.It AG_WIDGET_DOUBLE
.It AG_WIDGET_STRING
.It AG_WIDGET_POINTER
.It AG_WIDGET_FLAG
.It AG_WIDGET_FLAG8
.It AG_WIDGET_FLAG16
.It AG_WIDGET_FLAG32
.El
.Pp
The meaning of the following arguments depend on the type:
.Bl -tag -width "AG_WIDGET_STRING "
.It AG_WIDGET_STRING
Fixed-size, NUL-terminated string.
.Bl -tag -width "AG_Mutex *lock " -compact
.It Ft AG_Mutex *lock
Lock to acquire, or NULL.
.It Ft char *text
Fixed-size, NUL-terminated string.
.It Ft size_t bufsize
Total buffer size in bytes.
.El
.It AG_WIDGET_FLAG
One or more bits in a natural integer.
.Bl -tag -width "Uint bitmask " -compact
.It Ft Uint value
Flags value.
.It Ft Uint bitmask
Bitmask value.
.El
.It AG_WIDGET_FLAG8
One or more bits in a 8-bit integer.
.Bl -tag -width "Uint8 bitmask " -compact
.It Ft Uint8 value
Flags value.
.It Ft Uint8 bitmask
Bitmask value.
.El
.It AG_WIDGET_FLAG16
One or more bits in a 16-bit integer.
.Bl -tag -width "Uint16 bitmask " -compact
.It Ft Uint16 value
Flags value.
.It Ft Uint16 bitmask
Bitmask value.
.El
.It AG_WIDGET_FLAG32
One or more bits in a 32-bit integer.
.Bl -tag -width "Uint32 bitmask " -compact
.It Ft Uint32 value
Flags value.
.It Ft Uint32 bitmask
Bitmask value.
.El
.It AG_WIDGET_*
Other types of data.
.Bl -tag -width "AG_Mutex *lock " -compact
.It Ft AG_Mutex *lock
Lock to acquire, or NULL.
.It Ft void *p
Pointer to the data.
.El
.El
.Pp
The
.Fn AG_WidgetGetBinding
function returns a matching binding (locked), or NULL if none was found.
If a binding was found, a pointer to it is written in the
.Fa res
argument.
.Fn AG_WidgetGetBinding
is a
.Em deprecated
interface to
.Xr AG_GetVariable 3 .
.Pp
.Fn AG_WidgetUnlockBinding
should be called when done manipulating the data.
It is a
.Em deprecated
interface to
.Xr AG_UnlockVariable 3 .
.Pp
The
.Fn AG_WidgetCopyBinding
function copies the data (ie. type, pointer values) of the binding
.Fa src_binding
to
.Fa dst_binding .
The destination binding must already exist.
The function returns 0 on success, -1 if an error occured.
It is
.Em deprecated .
.Pp
The
.Fn AG_WidgetSet_*
routines are all simple variants of
.Fa AG_WidgetBind ,
with an implicit
.Fa type
argument.
The
.Fn AG_WidgetGet_*
routines return the current value of the specified binding.
.Pp
Note: Usages such as
.Fn AG_WidgetGetFoo
followed by
.Fn AG_WidgetSetFoo
are not thread-safe.
In such cases, the race condition can be avoided by using the
.Fn AG_WidgetGetBinding
interface, which requires explicit unlocking after use.
.Pp
.Fn AG_WidgetString
returns a copy of the string (or NULL on failure).
.Fn AG_WidgetCopyString
copies up to
.Fa dst_size
- 1 bytes from the string to
.Fa dst ,
NUL-terminating the result and returning the number of bytes that would
have been copied if
.Fa dst_size
was unlimited.
.Pp
NOTE: All
.Fn AG_WidgetGetFoo
and
.Fn AG_WidgetSetFoo
routines are
.Em deprecated
in favor of
.Fn AG_GetFoo
and
.Fn AG_SetFoo
(see
.Xr AG_Variable 3 ) .
.Sh WIDGET QUERIES
.nr nS 1
.Ft "AG_Window *"
.Fn AG_ParentWindow "AG_Widget *widget"
.Pp
.Ft "AG_Widget *"
.Fn AG_WidgetFind "AG_Display *view" "const char *name"
.Pp
.Ft "AG_Widget *"
.Fn AG_WidgetFindPoint "const char *classMask" "int x" "int y"
.Pp
.Ft "AG_Widget *"
.Fn AG_WidgetFindRect "const char *classMask" "int x" "int y" "int w" "int h"
.Pp
.nr nS 0
.Fn AG_ParentWindow
searches the parent objects of the given widget for an
.Xr AG_Window 3
(or a subclass of it).
If one is found, it is returned, otherwise the function returns NULL.
With threads, the return value is only valid as long as the view is locked
(see
.Xr AG_View 3 ) .
.Pp
.Fn AG_WidgetFind
searches for a given widget by name, given an absolute path,
and returns a pointer to the widget or NULL.
.Pp
.Fn AG_WidgetFindPoint
searches for a widget matching the given class mask enclosing the point
specified in display (pixel) coordinates.
The
.Fn AG_WidgetFindRect
variant requires that the widget enclose the specified rectangle.
.Pp
With threads, the return value of
.Fn AG_WidgetFind ,
.Fn AG_WidgetFindPoint
and
.Fn AG_WidgetFindRect
is only accurate as long as the
.Xr AG_View 3
VFS is locked.
.Sh GUI RENDERING
.nr nS 1
.Ft "void"
.Fn AG_WidgetDraw "AG_Widget *widget"
.Pp
.Ft "void"
.Fn AG_BeginRendering "void"
.Pp
.Ft "void"
.Fn AG_EndRendering "void"
.Pp
.nr nS 0
The
.Fn AG_WidgetDraw
routine renders a widget to the display.
It is typically invoked from an event loop routine (such as
.Xr AG_EventLoop 3 ) ,
to recursively draw the hierarchy of visible GUI elements.
.Pp
.Fn AG_WidgetDraw
invocations must be enclosed between calls to
.Fn AG_BeginRendering
and
.Fn AG_EndRendering .
.Sh THEME SELECTION
.nr nS 1
.Ft "void"
.Fn AG_SetStyle "AG_Widget *widget" "AG_Style *style"
.nr nS 0
.Pp
The
.Fn AG_SetStyle
function changes the style/theme associated with a widget.
See
.Xr AG_Style 3
for more information about styles.
Note that child widgets automatically inherit the style associated with
their parent.
.Sh THREAD SAFETY
Agar-GUI is thread-safe on a fine-grained level, so it is safe to make GUI
calls from different threads (unless documented otherwise in the widget's
manual page).
See
.Xr AG_Threads 3
for more details, including important conventions used throughout the
documentation.
.Sh EVENTS
The
.Nm
layer generates the following events:
.Pp
.Bl -tag -compact -width 2n
.It Fn widget-shown "void"
The widget is now visible.
.It Fn widget-hidden "void"
The widget is no longer visible.
.It Fn widget-enabled "void"
Input state has been enabled with
.Xr AG_WidgetEnable 3 .
.It Fn widget-disabled "void"
Input state has been disabled with
.Xr AG_WidgetDisable 3 .
.It Fn widget-moved "void"
The widget (or one of its parents) has been moved.
.It Fn widget-gainfocus "void"
The widget now holds focus inside its parent container.
.It Fn widget-lostfocus "void"
The widget no longer holds focus.
.It Fn widget-bound "AG_WidgetBinding *binding"
A widget binding has been added or modified.
NOTE: Do not use this event, use the
.Xr AG_Object 3
level
.Sq bound
event instead.
.El
.Sh STRUCTURE DATA
For the
.Ft AG_Widget
object:
.Pp
.Bl -tag -width "int cx2, cy2 "
.It Ft Uint flags
Option flags (see
.Dq FLAGS
section below).
.It Ft int x, y
Pixel coordinates of the widget relative to its parent.
.It Ft int w, h
Dimensions of the widget in pixels.
.It Ft int cx, cy
Absolute view coordinates of the upper left corner of the widget (read-only).
.It Ft int cx2, cy2
Absolute view coordinates of the lower right corner of the widget (read-only).
.El
.Sh FLAGS
The
.Va flags
member of the
.Nm
structure accepts the following flags:
.Bl -tag -width "AG_WIDGET_UNFOCUSED_BUTTONDOWN "
.It AG_WIDGET_HFILL
Hint to container widgets that in a vertical packing, this widget can expand
to fill all remaining space.
.It AG_WIDGET_VFILL
Hint to container widgets that in a horizontal packing, this widget can expand
to fill all remaining space.
.It AG_WIDGET_HIDE
Disable rendering of this widget (does not affect widget's children).
.It AG_WIDGET_DISABLED
Meaning is widget-specific but it generally disables user input (read-only,
set with
.Fn AG_WidgetDisable
and
.Fn AG_WidgetEnable ) .
See
.Dq INPUT STATE
section for more details.
.It AG_WIDGET_FOCUSABLE
The widget is allowed to grab the focus; normally set by
.Fn AG_WidgetSetFocusable .
Note that the widget may still become "focused" if child widgets are attached
to it and one of them happens to grab focus.
.It AG_WIDGET_UNFOCUSED_MOTION
Receive
.Sq window-mousemotion
events unconditionally (focus is required by default).
.It AG_WIDGET_UNFOCUSED_BUTTONUP
Receive
.Sq window-mousebuttonup
events unconditionally (focus is required by default).
.It AG_WIDGET_UNFOCUSED_BUTTONDOWN
Receive
.Sq window-mousebuttonup
events unconditionally (focus is required by default).
.It AG_WIDGET_CATCH_TAB
When the user presses the
.Dv TAB
key, generate normal
.Sq window-keydown
and
.Sq window-keyup
events.
Without this flag,
.Dv TAB
is used to change the focus to the next widget.
.It AG_WIDGET_NOSPACING
Advise parent container widgets to avoid applying spacing and padding rules
to this widget.
This flag is used by such widgets as
.Xr AG_Titlebar 3
and
.Xr AG_Menu 3 .
.El
.Sh EXAMPLES
See
.Pa demos/widgets
in the Agar source distribution.
.Sh SEE ALSO
.Xr AG_Style 3 ,
.Xr AG_Surface 3 ,
.Xr AG_View 3 ,
.Xr AG_Window 3
.Sh HISTORY
The
.Nm
interface first appeared in Agar 1.0.