diff options
| -rw-r--r-- | demos/modules/gwin/list/gfxconf.h | 150 | ||||
| -rw-r--r-- | demos/modules/gwin/list/main.c | 63 | ||||
| -rw-r--r-- | include/gwin/list.h | 147 | ||||
| -rw-r--r-- | src/gwin/list.c | 379 | 
4 files changed, 730 insertions, 9 deletions
diff --git a/demos/modules/gwin/list/gfxconf.h b/demos/modules/gwin/list/gfxconf.h new file mode 100644 index 00000000..895d7c49 --- /dev/null +++ b/demos/modules/gwin/list/gfxconf.h @@ -0,0 +1,150 @@ +/** + * This file has a different license to the rest of the GFX system. + * You can copy, modify and distribute this file as you see fit. + * You do not need to publish your source modifications to this file. + * The only thing you are not permitted to do is to relicense it + * under a different license. + */ + +/** + * Copy this file into your project directory and rename it as gfxconf.h + * Edit your copy to turn on the GFX features you want to use. + */ + +#ifndef _GFXCONF_H +#define _GFXCONF_H + +/* The operating system to use - one of these must be defined */ +//#define GFX_USE_OS_CHIBIOS		FALSE +//#define GFX_USE_OS_WIN32		FALSE +//#define GFX_USE_OS_LINUX		TRUE +//#define GFX_USE_OS_OSX			FALSE + +/* GFX subsystems to turn on */ +#define GFX_USE_GDISP			TRUE +#define GFX_USE_TDISP			FALSE +#define GFX_USE_GWIN			TRUE +#define GFX_USE_GEVENT			TRUE +#define GFX_USE_GTIMER			TRUE +#define GFX_USE_GQUEUE			TRUE +#define GFX_USE_GINPUT			TRUE +#define GFX_USE_GADC			FALSE +#define GFX_USE_GAUDIN			FALSE +#define GFX_USE_GAUDOUT			FALSE +#define GFX_USE_GMISC			FALSE + +/* Features for the GDISP subsystem */ +#define GDISP_NEED_VALIDATION		TRUE +#define GDISP_NEED_CLIP				TRUE +#define GDISP_NEED_TEXT				TRUE +#define GDISP_NEED_CIRCLE			TRUE +#define GDISP_NEED_ELLIPSE			TRUE +#define GDISP_NEED_ARC				FALSE +#define GDISP_NEED_CONVEX_POLYGON	FALSE +#define GDISP_NEED_SCROLL			FALSE +#define GDISP_NEED_PIXELREAD		FALSE +#define GDISP_NEED_CONTROL			FALSE +#define GDISP_NEED_QUERY			FALSE +#define GDISP_NEED_IMAGE			FALSE +#define GDISP_NEED_MULTITHREAD		FALSE +#define GDISP_NEED_ASYNC			FALSE +#define GDISP_NEED_MSGAPI			FALSE + +/* GDISP - builtin fonts */ +#define GDISP_INCLUDE_FONT_SMALL		FALSE +#define GDISP_INCLUDE_FONT_LARGER		FALSE +#define GDISP_INCLUDE_FONT_UI1			FALSE +#define GDISP_INCLUDE_FONT_UI2			TRUE +#define GDISP_INCLUDE_FONT_LARGENUMBERS	FALSE + +/* GDISP image decoders */ +#define GDISP_NEED_IMAGE_NATIVE		FALSE +#define GDISP_NEED_IMAGE_GIF		FALSE +#define GDISP_NEED_IMAGE_BMP		FALSE +#define GDISP_NEED_IMAGE_JPG		FALSE +#define GDISP_NEED_IMAGE_PNG		FALSE +#define GDISP_NEED_IMAGE_ACCOUNTING	FALSE + +/* Optional image support that can be turned off */ +/* +	#define GDISP_NEED_IMAGE_BMP_1		TRUE +	#define GDISP_NEED_IMAGE_BMP_4		TRUE +	#define GDISP_NEED_IMAGE_BMP_4_RLE	TRUE +	#define GDISP_NEED_IMAGE_BMP_8		TRUE +	#define GDISP_NEED_IMAGE_BMP_8_RLE	TRUE +	#define GDISP_NEED_IMAGE_BMP_16		TRUE +	#define GDISP_NEED_IMAGE_BMP_24		TRUE +	#define GDISP_NEED_IMAGE_BMP_32		TRUE +*/ + +/* Features for the TDISP subsystem. */ +#define TDISP_NEED_MULTITHREAD	FALSE + +/* Features for the GWIN subsystem. */ +#define GWIN_NEED_WINDOWMANAGER	TRUE +#define GWIN_NEED_CONSOLE		FALSE +#define GWIN_NEED_GRAPH			FALSE +#define GWIN_NEED_WIDGET		TRUE +#define GWIN_NEED_BUTTON		FALSE +#define GWIN_NEED_SLIDER		FALSE +#define GWIN_NEED_CHECKBOX		FALSE +#define GWIN_NEED_IMAGE			FALSE +#define GWIN_NEED_RADIO			FALSE +#define GWIN_NEED_LIST			TRUE + +/* Features for the GEVENT subsystem. */ +#define GEVENT_ASSERT_NO_RESOURCE	FALSE + +/* Features for the GTIMER subsystem. */ +/* NONE */ + +/* Features for the GQUEUE subsystem. */ +#define GQUEUE_NEED_ASYNC		TRUE +#define GQUEUE_NEED_GSYNC		FALSE +#define GQUEUE_NEED_FSYNC		FALSE + +/* Features for the GINPUT subsystem. */ +#define GINPUT_NEED_MOUSE		TRUE +#define GINPUT_NEED_KEYBOARD	FALSE +#define GINPUT_NEED_TOGGLE		FALSE +#define GINPUT_NEED_DIAL		FALSE + +/* Features for the GADC subsystem. */ +/* NONE */ + +/* Features for the GAUDIN subsystem. */ +/* NONE */ + +/* Features for the GAUDOUT subsystem. */ +/* NONE */ + +/* Features for the GMISC subsystem. */ +#define GMISC_NEED_ARRAYOPS		FALSE +#define GMISC_NEED_FASTTRIG		FALSE +#define GMISC_NEED_FIXEDTRIG	FALSE + +/* Optional Parameters for various subsystems */ +/* +	#define GDISP_MAX_FONT_HEIGHT			16 +	#define GEVENT_MAXIMUM_SIZE				32 +	#define GEVENT_MAX_SOURCE_LISTENERS		32 +	#define GTIMER_THREAD_WORKAREA_SIZE		512 +	#define GADC_MAX_LOWSPEED_DEVICES		4 +	#define GWIN_BUTTON_LAZY_RELEASE		FALSE +	#define GWIN_CONSOLE_USE_BASESTREAM		FALSE +	#define GWIN_CONSOLE_USE_FLOAT			FALSE +	#define GWIN_NEED_IMAGE_ANIMATION		FALSE +*/ + +/* Optional Low Level Driver Definitions */ +/* +	#define GDISP_USE_CUSTOM_BOARD		FALSE +	#define GDISP_SCREEN_WIDTH			320 +	#define GDISP_SCREEN_HEIGHT			240 +	#define GDISP_USE_FSMC +	#define GDISP_USE_GPIO +	#define TDISP_COLUMNS				16 +	#define TDISP_ROWS					2 +*/ + +#endif /* _GFXCONF_H */ diff --git a/demos/modules/gwin/list/main.c b/demos/modules/gwin/list/main.c new file mode 100644 index 00000000..35847be0 --- /dev/null +++ b/demos/modules/gwin/list/main.c @@ -0,0 +1,63 @@ +#include "gfx.h" + +static GListener gl; +static GHandle   ghList1; + +static void createWidgets(void) { +	GWidgetInit	wi; + +	// Apply some default values for GWIN +	wi.customDraw = 0; +	wi.customParam = 0; +	wi.customStyle = 0; +	wi.g.show = TRUE; + +	// Apply the list parameters +	wi.g.width = 300; +	wi.g.height = 200; +	wi.g.y = 10; +	wi.g.x = 10; +	wi.text = "List Name"; + +	// Create the actual list +	ghList1 = gwinListCreate(NULL, &wi); +} + +int main(void) { +	GEvent* pe; + +	// Initialize the display +	gfxInit(); + +	// Set the widget defaults +	gwinSetDefaultFont(gdispOpenFont("UI2")); +	gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE); +	gdispClear(White); + +	// Attach the mouse input +	gwinAttachMouse(0); + +	// create the widget +	createWidgets(); + +	// We want to listen for widget events +	geventListenerInit(&gl); +	gwinAttachListener(&gl); + +	// Add some items to the list widget +	gwinListAddItem(ghList1, "Item 0", TRUE); +	gwinListAddItem(ghList1, "Item 1", TRUE); +	gwinListAddItem(ghList1, "Item 2", TRUE); +	gwinListAddItem(ghList1, "Item 3", TRUE); +	gwinListAddItem(ghList1, "Item 4", TRUE); + +	gwinRedraw(ghList1); + +	while(1) { +		// Get an Event +		pe = geventEventWait(&gl, TIME_INFINITE); + +	} + +	return 0; +} diff --git a/include/gwin/list.h b/include/gwin/list.h index 0b525b03..ba83f24b 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -37,21 +37,164 @@   * @brief	A list event   */  typedef struct GEventGWinList { -	GEventType		type;			// The type of this event (GEVENT_GWIN_LIST) -	GHandle			list;			// THe list that has generated the event +	GEventType		type;		// The type of this event (GEVENT_GWIN_LIST) +	GHandle			list;		// The list +	int				item;		// The item that has been selected (or unselected in a multi-select listbox)  } GEventGWinList;  // A list window  typedef struct GListObject {  	GWidgetObject	w; +	int				cnt;		// Number of items currently in the list (quicker than counting each time) +	gfxQueueASync	list_head;	// The list of items  } GListObject;  #ifdef __cplusplus  extern "C" {  #endif +/** + * @brief				Create a list widget + * + * @note				The drawing color and the background color get set to the current defaults. If you haven't called + *						@p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are Black and White. + * @note				The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then + *						there is no default font and text drawing operations will not display anything. + * @note				A list remembers its normal drawing state. If there is a window manager then it is automatically + *						redrawn if the window is moved or its visibility state is changed. + * @note				The list contains no elements after creation. + * @note				A slider supports mouse, toggle and dial input. + * @note				When assigning a toggle, only one toggle is supported per role. If you try to assign more than + *						one toggle to a role, it will forget the previous toggle. Two roles are supported: + *						Role 0 = toggle for down, role 1 = toggle for up  + * @note				When assigning a dial, only one dial is supported. If you try to assign more than one dial, it + *						will forget the previous dial. Only dial role 0 is supported. + * + * @param[in] widget	The GListObject structure to initialize. If this is NULL, the structure is dynamically allocated. + * @param[in] pInit		The initialization parameters to use + * + * @return				NULL if there is no resulting drawing area, otherwise a window handle. + * + * @api + */  GHandle gwinListCreate(GListObject *widget, GWidgetInit *pInit); +/** + * @brief				Add an item to the list + * + * @note				The ID you get returned is not static. If items get removed from the list, the list items get + * 						reordered. + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] item		The string which shall be displayed in the list afterwards + * @param[in] useAlloc	If set to TRUE, the string will be dynamically allocated. A static buffer must be passed otherwise + * + * @return				The current ID of the item. The ID might change if you remove items from the middle of the list + * + * @api + */ +int gwinListAddItem(GHandle gh, const char* item, bool_t useAlloc); + +/** + * @brief				Get the name behind an item with a given ID + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] item		The item ID + * + * @return				The string of the list item or NULL on error + * + * @api + */ +char* gwinListItemGetText(GHandle gh, int item); + +/** + * @brief				Get the ID of an item with a given name + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] text		The item name + * + * @return				The id of the list item or -1 on error + * + * @api + */ +int gwinListFindText(GHandle gh, const char* text); + +/** + * @brief				Set the custom parameter of an item with a given ID + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] item		The item ID + * @param[in] param		The parameter to be set + * + * @api + */ +void gwinListItemSetParam(GHandle gh, int item, uint16_t param); + +/** + * @brief				Get the custom parameter of an item with a given ID + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] item		The item ID + * + * @return				The parameter + * + * @api + */ +uint16_t gwinListItemGetParam(GHandle gh, int item); + +/** + * @brief				Delete all the items of the list + * + * @param[in] gh		The widget handle (must be a list handle) + * + * @api + */ +void ListDeleteAll(GHandle gh); + +/** + * @brief				Delete an item from the list + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] item		The item ID + * + * @api + */ +void gwinListItemDelete(GHandle gh, int item); + +/** + * @brief				Get the amount of items within the list + * + * @param[in] gh		The widget handle (must be a list handle) + * + * @return				The amount of items in the list + * + * @api + */ +int gwinListItemCount(GHandle gh); + +/** + * @brief				Check if an item with a given ID is selected + * + * @param[in] gh		The widget handle (must be a list handle) + * @param[in] item		The item ID + * + * @return				TRUE if the item is selected, FALSE otherwise + * + * @api + */ +bool_t gwinListItemIsSelected(GHandle gh, int item); + +/** + * @brief				Get the ID of the selected item + * + * @param[in] gh		The widget handle (must be a list handle) + * + * @return				The ID of the list item + * + * @api + */ +int gwinListGetSelected(GHandle gh); +  #ifdef __cplusplus  }  #endif diff --git a/src/gwin/list.c b/src/gwin/list.c index eae9bb46..f495ada4 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -20,34 +20,199 @@  #if GFX_USE_GWIN && GWIN_NEED_LIST  #include "gwin/class_gwin.h" +#include <string.h> + +// user for the default drawing routine +#define BORDER			3	// the border from the the text to the frame +#define BORDER_SCROLL	20	// the border from the scroll buttons to the frame +#define ARROW			10	// arrow side length + +#define widget(gh)	((GListObject *)gh) + +#define GLIST_FLG_MULTISELECT		(GWIN_FIRST_CONTROL_FLAG << 0) +#define GLIST_FLG_HASIMAGES			(GWIN_FIRST_CONTROL_FLAG << 1) +#define GLIST_FLG_SELECTED			(GWIN_FIRST_CONTROL_FLAG << 2) + +typedef struct ListItem { +	gfxQueueASyncItem	q_item;		// This must be the first member in the struct + +	uint16_t			flags; +	uint16_t			param;		// A parameter the user can specify himself +	const char*			text; +	#if GWIN_LIST_IMAGES +	gdispImage*			pimg; +	#endif +} ListItem; + +void _selectUp(GWidgetObject *gw) { +	#define gcw			((GListObject *)gw) + +	gfxQueueASyncItem	*qi; +	uint16_t i; + +	for (i = 0, qi = gfxQueueASyncPeek(&gcw->list_head); qi; qi = gfxQueueASyncNext(qi), i++) { +		if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED && i < gcw->cnt - 1) { +			((ListItem*)qi)->flags &=~ GLIST_FLG_SELECTED; +			qi = gfxQueueASyncNext(qi); +			((ListItem*)qi)->flags |= GLIST_FLG_SELECTED;	 +		} +	} + +	_gwidgetRedraw((GHandle)gw); + +	#undef gcw +} + +static void _selectDown(GWidgetObject *gw) { +	#define gcw			((GListObject *)gw) + +	_gwidgetRedraw((GHandle)gw); + +	#undef gcw +} + +static void sendListEvent(GWidgetObject *gw, int item) { +	GSourceListener*	psl; +	GEvent*				pe; +	#define pse			((GEventGWinList *)pe) + +	// Trigger a GWIN list event +	psl = 0; + +	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { +		if (!(pe = geventGetEventBuffer(psl))) +			continue; + +		pse->type = GEVENT_GWIN_LIST; +		pse->list = (GHandle)gw; +		pse->item = item; + +		geventSendEvent(psl); +	} +	 +	#undef pse	 +}  static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { +	#define gcw			((GListObject *)gw) +	(void)param; + +	uint16_t i, fheight; +	const point upArrow[] = { {0, ARROW}, {ARROW, ARROW}, {ARROW/2, 0} }; +	const point downArrow[] = { {0, 0}, {ARROW, 0}, {ARROW/2, ARROW} }; +	const gfxQueueASyncItem* qi; + +	fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight);	 + +	// the list frame +	gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->enabled.edge); +	gdispDrawLine(gw->g.x + gw->g.width - BORDER_SCROLL, gw->g.y, gw->g.x + gw->g.width - BORDER_SCROLL, gw->g.y + gw->g.height, gw->pstyle->enabled.edge); +	gdispDrawLine(gw->g.x + gw->g.width - BORDER_SCROLL, gw->g.y + BORDER_SCROLL, gw->g.x + gw->g.width, gw->g.y + BORDER_SCROLL, gw->pstyle->enabled.edge); +	gdispDrawLine(gw->g.x + gw->g.width - BORDER_SCROLL, gw->g.y + gw->g.height - BORDER_SCROLL, gw->g.x + gw->g.width, gw->g.y + gw->g.height - BORDER_SCROLL, gw->pstyle->enabled.edge); + +	// the up-button +	gdispFillConvexPoly(gw->g.x + gw->g.width - BORDER_SCROLL + ARROW/2, gw->g.y + BORDER_SCROLL - ARROW - ARROW/2, upArrow, 3, gw->pstyle->enabled.edge); +	 +	// the down-button +	gdispFillConvexPoly(gw->g.x + gw->g.width - BORDER_SCROLL + ARROW/2, gw->g.y + gw->g.height - BORDER_SCROLL + ARROW/2, downArrow, 3, gw->pstyle->enabled.edge); + +	for (qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i += fheight + 2*BORDER) { +		if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) { +			gdispFillStringBox(gw->g.x + BORDER, gw->g.y + BORDER + i, gw->g.width - 2*BORDER - BORDER_SCROLL, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), gw->pstyle->background, gw->pstyle->enabled.text, justifyLeft); +		} else { +			gdispFillStringBox(gw->g.x + BORDER, gw->g.y + BORDER + i, gw->g.width - 2*BORDER - BORDER_SCROLL, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), gw->pstyle->enabled.text, gw->pstyle->background, justifyLeft); +		} +	} + +	#undef gcw +} + +#if GINPUT_NEED_MOUSE +	// a mouse down has occured over the list area +	static void MouseDown(GWidgetObject* gw, coord_t x, coord_t y) { +		#define gcw			((GListObject *)gw) +		#define li			((ListItem *)qi) +		(void)				x; + +		uint16_t i, item_id, item_height; +		const gfxQueueASyncItem* qi; + +		item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2*BORDER; +		item_id = (y - gw->g.y) / item_height; + +		for(qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { +			if (item_id == i) +				li->flags |= GLIST_FLG_SELECTED; +			else +				li->flags &=~ GLIST_FLG_SELECTED; +		} + +		_gwidgetRedraw((GHandle)gw); + +		// do not generate an event if an empty section of the list has has been selected +		if (item_id < 0 || item_id > gcw->cnt - 1) +			return; + +		sendListEvent(gw, item_id); + +		#undef gcw +		#undef li +	} +#endif + +#if GINPUT_NEED_TOGGLE +	// a toggle-on has occurred +	static void ToggleOn(GWidgetObject *gw, uint16_t role) { +		#define gcw			((GListObject *)gw) + +		switch (role) { +			// select up +			case 0: +				_selectUp(gw); +				break; + +			// select down +			case 1: +				_selectDown(gw); +				break; +		} + +		#undef gcw +	} +#endif + +static void _destroy(GHandle gh) { +	const gfxQueueASyncItem* qi; +	while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) +		gfxFree((void *)qi); + +	_gwidgetDestroy(gh);  }  static const gwidgetVMT listVMT = {  	{  		"List",					// The class name  		sizeof(GListObject),	// The object size -		_gwidgetDestroy,		// The destroy routine +		_destroy,				// The destroy routine  		_gwidgetRedraw,			// The redraw routine  		0,						// The after-clear routine  	},  	gwinListDefaultDraw,		// default drawing routine -	#if GWINPUT_NEED_MOUSE +	#if GINPUT_NEED_MOUSE  		{ -			0, +			MouseDown,  			0,  			0,  		},  	#endif  	#if GINPUT_NEED_TOGGLE  		{ +			2,					// two toggle roles +			ToggleAssin,		// Assign toggles +			ToggleGet,			// get toggles  			0, -			0, -			0, -			0, -			0, +			ToggleOn,			// process toggle on event  		},  	#endif  	#if GINPUT_NEED_DIAL @@ -64,11 +229,211 @@ GHandle gwinListCreate(GListObject* widget, GWidgetInit* pInit) {  	if (!(widget = (GListObject *)_gwidgetCreate(&widget->w, pInit, &listVMT)))  		return 0; +	// initialize the item queue +	gfxQueueASyncInit(&(widget->list_head)); +	widget->cnt = 0; +  	gwinSetVisible(&widget->w.g, pInit->g.show);  	return (GHandle)widget;  } +int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { +	size_t		sz; +	ListItem	*newItem; + +	sz = useAlloc ? sizeof(ListItem)+strlen(item_name)+1 : sizeof(ListItem); + +	if (!(newItem = (ListItem *)gfxAlloc(sz))) +		return -1; + +	if (useAlloc) { +		strcpy((char *)(newItem+1), item_name); +		item_name = (const char *)(newItem+1); +	} + +	// the item is not selected when added +	newItem->flags = 0; +	newItem->param = 0; +	newItem->text = item_name; + +	// select the item if it's the first in the list +	if (widget(gh)->cnt == 0) +		newItem->flags |= GLIST_FLG_SELECTED; + +	// add the new item to the list +	gfxQueueASyncPut(&widget(gh)->list_head, &newItem->q_item); + +	// increment the total amount of entries in the list widget +	widget(gh)->cnt++; + +	// return the position in the list (-1 because we start with index 0) +	return widget(gh)->cnt-1; +} + +char* gwinListItemGetText(GHandle gh, int item) { +	const gfxQueueASyncItem* qi; +	uint16_t i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return 0; + +	// watch out for an invalid item +	if (item < 0 || item > (widget(gh)->cnt) - 1) +		return 0; + +	qi = gfxQueueASyncPeek(&widget(gh)->list_head); +	 +	for (i = 0; i < item; i++) { +		qi = gfxQueueASyncNext(qi); +	} + +	return ((ListItem*)qi)->text; +} + +int gwinListFindText(GHandle gh, const char* text) { +	const gfxQueueASyncItem* qi; +	uint16_t i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return -1; + +	// watch out for NULL pointers +	if (!text) +		return -1; + +	qi = gfxQueueASyncPeek(&widget(gh)->list_head); +	 +	for(qi = gfxQueueASyncPeek(&widget(gh)->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { +		if (strcmp(((ListItem *)qi)->text, text) == 0) +			return i;	 +	} + +	return -1; +} + +int gwinListGetSelected(GHandle gh) { +	const gfxQueueASyncItem	*qi; +	int i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return -1; + +	for(qi = gfxQueueASyncPeek(&widget(gh)->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { +		if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) +			return i; +	} + +	return -1; +} + +void gwinListItemSetParam(GHandle gh, int item, uint16_t param) { +	const gfxQueueASyncItem* qi; +	uint16_t i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return; + +	// watch out for an invalid item +	if (item < 0 || item > (widget(gh)->cnt) - 1) +		return; + +	qi = gfxQueueASyncPeek(&widget(gh)->list_head); +	 +	for (i = 0; i < item; i++) { +		((ListItem*)qi)->param = param; +	} + +	return;	 +} + +void gwinListDeleteAll(GHandle gh) { +	const gfxQueueASyncItem* qi; + +	while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) +		gfxFree((void *)qi); +} + +void gwinListItemDelete(GHandle gh, int item) { +	const gfxQueueASyncItem* qi; +	uint16_t i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return; + +	// watch out for an invalid item +	if (item < 0 || item > (widget(gh)->cnt) - 1) +		return; + +	qi = gfxQueueASyncPeek(&widget(gh)->list_head); + +	// get our item pointer	 +	for (i = 0; i < item; i++) { +		qi = gfxQueueASyncNext(qi); +	} + +	gfxQueueASyncRemove(&widget(gh)->list_head, qi); +	gfxFree((void*)qi); +} + +uint16_t gwinListItemGetParam(GHandle gh, int item) { +	const gfxQueueASyncItem* qi; +	uint16_t i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return 0; + +	// watch out for an invalid item +	if (item < 0 || item > (widget(gh)->cnt) - 1) +		return 0; + +	qi = gfxQueueASyncPeek(&widget(gh)->list_head); +	 +	for (i = 0; i < item; i++) { +		qi = gfxQueueASyncNext(qi); +	} + +	return ((ListItem*)qi)->param; +} + +bool_t gwinListItemIsSelected(GHandle gh, int item) { +	const gfxQueueASyncItem* qi; +	uint16_t i; + +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return FALSE; + +	// watch out for an invalid item +	if (item < 0 || item > (widget(gh)->cnt) - 1) +		return FALSE; + +	qi = gfxQueueASyncPeek(&widget(gh)->list_head); +	 +	for (i = 0; i < item; i++) { +		qi = gfxQueueASyncNext(qi); +	} + +	if (((ListItem*)qi)->flags &  GLIST_FLG_SELECTED) +		return TRUE; +	else +		return FALSE; +} + +int gwinListItemCount(GHandle gh) { +	// is it a valid handle? +	if (gh->vmt != (gwinVMT *)&listVMT) +		return 0; + +	return widget(gh)->cnt; +} +  #endif // GFX_USE_GWIN && GWIN_NEED_LIST  /** @} */  | 
