AG_TLIST(3)

NAME
AG_Tlist - agar tree/list widget

SYNOPSIS

    #include <agar/core.h>
    #include <agar/gui.h>

DESCRIPTION
The AG_Tlist widget shows a scrollable tree / list of clickable and selectable items. Items can display text and icons. Items include user-defined data fields (a signed integer v, an unsigned integer u, a user pointer p1 and a general-purpose category string cat).

For cases where the contents of the tree or list may change externally, a polling routine may be defined. Such a routine is expected to clear and repopulate the list entirely. It may be run periodically at a specified interval, whenever user interaction events occur, or by explicit call to AG_TlistRefresh(). To make polling more efficient (and to preserve per-item states such as selections across polling cycles), AG_Tlist relies on a compare function to test items for equivalence and reuse assets (including allocated structures and rendered text surfaces).

INHERITANCE HIERARCHY
AG_Object(3) -> AG_Widget(3) -> AG_Tlist.

INITIALIZATION
AG_Tlist * AG_TlistNew(AG_Widget *parent, Uint flags)

AG_Tlist * AG_TlistNewPolled(AG_Widget *parent, Uint flags, void (*eventFn)(AG_Event *), const char *eventArgs, ...)

AG_Tlist * AG_TlistNewPolledMs(AG_Widget *parent, Uint flags, int ms, void (*eventFn)(AG_Event *), const char *eventArgs, ...)

void AG_TlistSetRefresh(AG_Tlist *tl, int ms)

void AG_TlistRefresh(AG_Tlist *tl)

void AG_TlistSetItemHeight(AG_Tlist *tl, int item_height)

void AG_TlistSetIconWidth(AG_Tlist *tl, int icon_width)

void AG_TlistSizeHint(AG_Tlist *tl, const char *text, int nItems)

void AG_TlistSizeHintPixels(AG_Tlist *tl, int w, int nItems)

void AG_TlistSizeHintLargest(AG_Tlist *tl, int nItems)

void AG_TlistSetDblClickFn(AG_Tlist *tl, AG_EventFn fn, const char *fn_args, ...)

void AG_TlistSetChangedFn(AG_Tlist *tl, AG_EventFn fn, const char *fn_args, ...)

AG_TlistNew() allocates, initializes, and attaches a AG_Tlist widget.

The AG_TlistNewPolled() variant enables AG_TLIST_POLL and sets the specified polling routine eventFn to run periodically (or -1 = never). The polling routine is expected to clear and populate the AG_Tlist. The AG_TlistNewPolledMs() variant sets the update rate to ms milliseconds.

Acceptable flags include:

AG_TLIST_EXPAND_NODES
    Expand nodes with child items by default.

AG_TLIST_MULTI
    Allow multiple selections (with ctrl/shift).

AG_TLIST_MULTITOGGLE
    Enforce multiple selections (without ctrl/shift).

AG_TLIST_POLL
    List contents are updated dynamically by the "tlist-poll" handler. This handler is expected to wrap its AG_TlistAdd() calls between AG_TlistBegin() and AG_TlistEnd(). Implied by AG_TlistNewPolled().

AG_TLIST_FIXED_HEIGHT
    Don't reset the item height on "font-changed".

AG_TLIST_NO_LINES
    Don't draw lines between nodes.

AG_TLIST_NO_KEYREPEAT
    Disable keyrepeat behavior.

AG_TLIST_NO_SELECTED
    Don't raise "tlist-selected" on select.

AG_TLIST_STATELESS
    When using AG_TLIST_POLL, don't preserve selection information across list updates.

AG_TLIST_HFILL
    Expand horizontally in parent container.

AG_TLIST_VFILL
    Expand vertically in parent container.

AG_TLIST_EXPAND
    Shorthand for AG_TLIST_HFILL | AG_TLIST_VFILL.

AG_TlistSetRefresh() sets the rate at which the polling routine will be invoked in milliseconds (default = 1s). A value of -1 disables automatic updates. When automatic updates are disabled, updates can be performed by calling AG_TlistRefresh(). See the AG_TLIST_POLL option for details.

AG_TlistSetItemHeight() sets the given, uniform height of all items. AG_TlistSetIconWidth() sets the width of item icons in pixels.

AG_TlistSizeHint() requests sufficient height to display nItems items at once, and sufficient width to display an item containing text. The AG_TlistSizeHintPixels() variant accepts a width argument in pixels instead of a string and the AG_TlistSizeHintLargest() variant uses the largest text label in the current list of items to determine the width.

AG_TlistSetDblClickFn() arranges for the given callback fn to be invoked with the given arguments (as well as the item pointer) when the user double clicks on an item.

AG_TlistSetChangedFn() arranges for the callback fn to be invoked when the user selects or deselects an item. The arguments are respectively, a pointer to the item and an integer with a value of 0 to indicate deselection and 1 to indicate selection.

COMPARE FUNCTIONS
AG_TlistCompareFn AG_TlistSetCompareFn(AG_Tlist *tl, AG_TlistCompareFn fn)

int AG_TlistCompareInts(const AG_TlistItem *a, const AG_TlistItem *b))

int AG_TlistCompareUints(const AG_TlistItem *a, const AG_TlistItem *b))

int AG_TlistCompareStrings(const AG_TlistItem *a, const AG_TlistItem *b))

int AG_TlistComparePtrs(const AG_TlistItem *a, const AG_TlistItem *b))

int AG_TlistComparePtrsAndCats(const AG_TlistItem *a, const AG_TlistItem *b))

In order for AG_Tlist to be able to preserve per-item states (such as selections) through polling updates when using a polling function, it is necessary to be able to establish equivalence between items. The nature of this equivalence is application-defined and is determined by the compare function selected. The AG_TlistUniq() routine (see below) also relies on the compare function.

AG_TlistSetCompareFn() sets the comparison function to use when testing between two AG_TlistItem for equivalence. It returns a pointer to the previously selected compare function. Compare functions are defined as:

    typedef int (*AG_TlistCompareFn)(const AG_TlistItem *a,
    	                         const AG_TlistItem *b);

It is expected to return 0 if the two items are equivalent and non-zero if the items are not. If the returned value if non-zero, it can be used to define the sorting order. Returning a positive value in the case where (a > b) should produce a sort in descending order.

Some basic compare functions are provided:

AG_TlistCompareInts() compares the signed integer field v1.

AG_TlistCompareUints() compares the unsigned integer field u.

AG_TlistCompareStrings() compares the text strings lexicographically. The comparison is case-sensitive and ignores any locale collation.

AG_TlistComparePtrs() compares the pointer fields p1. This is the default compare function.

AG_TlistComparePtrsAndCats() compares both p1 and the category cat.

MANIPULATING ITEMS
AG_TlistItem * AG_TlistAdd(AG_Tlist *tl, const AG_Surface *icon, const char *format, ...)

AG_TlistItem * AG_TlistAddS(AG_Tlist *tl, const AG_Surface *icon, const char *text)

AG_TlistItem * AG_TlistAddHead(AG_Tlist *tl, const AG_Surface *icon, const char *format, ...)

AG_TlistItem * AG_TlistAddHeadS(AG_Tlist *tl, const AG_Surface *icon, const char *text)

AG_TlistItem * AG_TlistAddPtr(AG_Tlist *tl, const AG_Surface *icon, const char *text, const void *p1)

AG_TlistItem * AG_TlistAddPtrHead(AG_Tlist *tl, const AG_Surface *icon, const char *text, const void *p1)

void AG_TlistMoveToHead(AG_Tlist *tl, AG_TlistItem *item)

void AG_TlistMoveToTail(AG_Tlist *tl, AG_TlistItem *item)

void AG_TlistSetIcon(AG_Tlist *tl, AG_TlistItem *item, const AG_Surface *icon)

void AG_TlistSetColor(AG_Tlist *tl, AG_TlistItem *item, const AG_Color *color)

void AG_TlistSetFont(AG_Tlist *tl, AG_TlistItem *item, const char *face, float scale, Uint flags)

void AG_TlistDel(AG_Tlist *tl, AG_TlistItem *item)

void AG_TlistSort(AG_Tlist *tl)

void AG_TlistSortByInt(AG_Tlist *tl)

void AG_TlistUniq(AG_Tlist *tl)

void AG_TlistClear(AG_Tlist *tl)

void AG_TlistBegin(AG_Tlist *tl)

void AG_TlistEnd(AG_Tlist *tl)

int AG_TlistVisibleChildren(AG_Tlist *tl, AG_TlistItem *item)

void AG_TlistSelect(AG_Tlist *tl, AG_TlistItem *item)

void AG_TlistSelectIdx(AG_Tlist *tl, Uint index)

void AG_TlistSelectAll(AG_Tlist *tl)

void AG_TlistDeselect(AG_Tlist *tl, AG_TlistItem *item)

void AG_TlistDeselectIdx(AG_Tlist *tl, Uint index)

void AG_TlistDeselectAll(AG_Tlist *tl)

AG_TlistItem * AG_TlistSelectPtr(AG_Tlist *tl, void *ptr)

AG_TlistItem * AG_TlistSelectText(AG_Tlist *tl, const char *text)

AG_TlistItem * AG_TlistFindByIndex(AG_Tlist *tl, int index)

AG_TlistItem * AG_TlistSelectedItem(AG_Tlist *tl)

void * AG_TlistSelectedItemPtr(AG_Tlist *tl)

void * AG_TLIST_ITEM(idx)

int AG_TlistFindPtr(AG_Tlist *tl, void **p)

AG_TlistItem * AG_TlistFindText(AG_Tlist *tl, const char *text)

AG_TlistItem * AG_TlistFirstItem(AG_Tlist *tl)

AG_TlistItem * AG_TlistLastItem(AG_Tlist *tl)

void AG_TlistScrollToStart(AG_Tlist *tl)

void AG_TlistScrollToEnd(AG_Tlist *tl)

void AG_TlistScrollToSelection(AG_Tlist *tl)

AG_TlistAdd() inserts a newly-allocated item into the list and returns a pointer to it. If icon is not NULL, it specifies an AG_Surface(3) to duplicate and display as an icon.

The AG_TlistAddHead() variant places the item at the head of the list. The AG_TlistAddPtr() variant of AG_TlistAdd() also sets the pointer field p1 on initialization.

AG_TlistAddPtrHead() places the item at the head of the list.

AG_TlistMoveToHead() moves an existing item item to the head of the list. AG_TlistMoveToTail() moves an existing item item to the tail of the list.

AG_TlistSetIcon() sets the icon surface associated with item. A duplicate of the given surface will be used.

AG_TlistSetColor() sets an alternate text color for the specified item (or NULL to switch back to the default).

AG_TlistSetFont() sets an alternate font for the specified item. If face is NULL, use the same font face as the tlist's font. scale sets the size of the font relative to the tlist's font. If scale is 1.0f then the same size will be used. The flags argument is the set of AG_Font(3) style flags (such as AG_FONT_BOLD).

The AG_TlistDel() function detaches and frees item from its parent tl.

The AG_TlistSort() routine lexicographically sorts the items in the list by text according to the current locale collation.

AG_TlistSortByInt() sorts items based on their integer values v.

AG_TlistUniq() scans the list for duplicates and removes them. AG_TlistUniq() uses the compare function to determine equivalence between items (see AG_TlistSetCompareFn()).

AG_TlistClear() removes all items attached to the list.

The AG_TlistBegin() function removes all items attached to tl, but remembers their selection and child item expansion states. AG_TlistEnd() compares each item against the saved state and restores the selection and child item expansion states accordingly.

The AG_TlistVisibleChildren() function is meant to be called from a polling routine. It tests whether a newly-created item should make its own child items visible based on the previously saved state. If there are no matching items in the saved state (according to the Compare function), then it returns the default visibility setting (which is 1 if the AG_TLIST_EXPAND_NODES option is set, otherwise 0).

AG_TlistSelect() sets the selection flag on item (clearing any previous selection unless AG_TLIST_MULTI is set). AG_TlistDeselect() clears the selection flag on item. AG_TlistSelectIdx() and AG_TlistDeselectIdx() reference the target AG_TlistItem by index rather than by pointer.

AG_TlistSelectAll() AG_TlistDeselectAll() sets / clears the selection on all items attached to tl.

The AG_TlistSelectPtr() function selects and returns the first item with a user pointer value matching ptr. Similarly, AG_TlistSelectText() selects and returns the first item with a text field equal to text. Both of these functions invoke "tlist-poll" if the AG_TLIST_POLL option is set.

The AG_TlistFindByIndex() function returns the item at index, or NULL if there is no such item. The AG_TlistSelectedItem() function returns the first selected item, or NULL if there are none.

The AG_TlistSelectedItemPtr() function returns the user pointer of the first selected item, or NULL if there is no selected item. It is not possible to distinguish a non-existent selection from an actual selection with a NULL user pointer using this function.

In event handler context, the AG_TLIST_ITEM() macro is a shortcut for AG_TlistSelectedItemPtr() on item n from the event stack.

The AG_TlistFindPtr() variant copies the user pointer associated with the first selected item into p, returning 0 on success or -1 if there is no item selected. The AG_TlistFindText() function searches tl for an item containing the text string and returns NULL if there is no such item.

The AG_TlistFirstItem() and AG_TlistLastItem() functions return the first and last items on the list.

AG_TlistScrollToStart() scrolls the display to the start and AG_TlistScrollToEnd() scrolls the display to the end of the list.

AG_TlistScrollToSelection() scrolls to make the first selected item visible. It's a no-op if there are no selected items.

POPUP MENUS
AG_MenuItem * AG_TlistSetPopupFn(AG_Tlist *tl, AG_EventFn fn, const char *fn_args, ...)

AG_MenuItem * AG_TlistSetPopup(AG_Tlist *tl, const char *category)

The AG_TlistSetPopupFn() function arranges for the given callback fn to be invoked with the given arguments whenever the user right-clicks on an item on the list. A pointer to the selected item is passed as the last argument to this function. Typically, the function will use AG_PopupNew(3) to display a popup menu.

The AG_TlistSetPopup() function creates a popup menu that will be displayed when the user right-clicks on any item that matches the given category string.

EVENTS
The AG_Tlist widget generates the following events:

tlist-changed(AG_TlistItem *item, int state)
    item was selected or unselected.
tlist-selected(AG_TlistItem *item)
    item was selected.
tlist-dblclick(AG_TlistItem *item)
    The user just double-clicked item. Binding to this event is equivalent to using AG_TlistSetDblClickFn().
tlist-return(AG_TlistItem *item)
    The user has selected item and pressed the return key.
tlist-poll(void)
    The AG_TLIST_POLL flag is set and the widget is about to be drawn or an event is being processed.

BINDINGS
The AG_Tlist widget provides the following bindings:

void *selected
    The p1 (user pointer) value of the selected item, or NULL if there is no selection. The value of this binding is undefined if the AG_TLIST_MULTI or AG_TLIST_MULTITOGGLE flags are in use.

STRUCTURE DATA
For the AG_Tlist object:

TAILQ items
    The list of items (linkage is read-only).
int nItems
    Number of items in total (read-only).
int nVisible
    Number of items on screen (read-only).
Uint pollDelay
    Delay in between updates in AG_TLIST_POLL mode (ms).

For the AG_TlistItem structure:

int selected
    Selection flag.
void *p1
    User pointer (application-defined).
int v
    User signed integer value (application-defined).
Uint u
    User unsigned integer value (application-defined).
const char *cat
    Category string (application-defined).
char text[]
    Text label (up to AG_TLIST_LABEL_MAX characters).
int depth
    Depth in tree (0 = root).
Uint flags
    Item flags (see ITEM FLAGS section below).
float scale
    Scaling factor for text display (default = 1.0).

ITEM FLAGS
AG_TLIST_ITEM_DISABLED
    Disable selection and draw in DISABLED style.
AG_TLIST_NO_SELECT
    Disable selection and draw in DEFAULT style.
AG_TLIST_ITEM_EXPANDED
    Child items are visible.
AG_TLIST_HAS_CHILDREN
    At least one child item exists.
AG_TLIST_NO_POPUP
    Disable popup menus (if any have been created).

EXAMPLES
The following code fragment displays an external tree structure using a recursive polling routine.

    MyTreeNode *myTreeRoot;
    AG_Window *win;
    static void
    PollMyTreeNode(AG_Tlist *tl, MyTreeNode *node, int depth)
    {
    	AG_TlistItem *ti;
    	ti = AG_TlistAdd(tl, NULL, "Node %s", node->name);
    	ti->flags |= AG_TLIST_HAS_CHILDREN;
    	ti->p1 = node;
    	ti->depth = depth;
    	if (AG_TlistVisibleChildren(tl, ti)) {
    		MyTreeNode *child;
    		LIST_FOREACH(child, &node->children, children)
    			PollMyTreeNode(tl, child, depth+1);
    	}
    }
    static void
    PollMyTree(AG_Event *event)
    {
    	AG_Tlist *tl = AG_TLIST_SELF();
    	MyTreeNode *root = AG_PTR(1);
    	AG_TlistBegin(tl);
    	PollMyTreeNode(tl, root, 0);
    	AG_TlistEnd(tl);
    }
    myTreeRoot = InitMyTree();
    win = AG_WindowNew(0);
    AG_TlistNewPolled(win, 0, PollMyTree, "%p", myTreeRoot);

SEE ALSO
AG_Intro(3), AG_Table(3), AG_Treetbl(3), AG_Widget(3), AG_Window(3)

HISTORY
The AG_Tlist widget first appeared in Agar 1.0. AG_TlistSelectIdx(), AG_TlistDeselectIdx(), AG_TlistSetColor() and AG_TlistSetFont() appeared in Agar 1.6.0. Options AG_TLIST_EXPAND_NODES, AG_TLIST_FIXED_HEIGHT, AG_TLIST_NO_LINES, AG_TLIST_NO_KEYREPEAT and the per-item flag AG_TLIST_ITEM_DISABLED appeared in Agar 1.7.0. The u and v integer fields and AG_TlistCompareInts() and AG_TlistCompareUints() appeared in Agar 1.7.0.