From 57eeb16aba2613c1329eafbf7d7453cd67f2cc69 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Thu, 25 Jul 2013 19:15:51 +0200 Subject: [PATCH 01/18] list widget - work in progress --- include/gos/linux.h | 1 + include/gwin/list.h | 9 ++- src/gwin/list.c | 143 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 149 insertions(+), 4 deletions(-) diff --git a/include/gos/linux.h b/include/gos/linux.h index 7529a962..508b2b68 100644 --- a/include/gos/linux.h +++ b/include/gos/linux.h @@ -16,6 +16,7 @@ #if GFX_USE_OS_LINUX #include +#include #include #include diff --git a/include/gwin/list.h b/include/gwin/list.h index 0b525b03..46e32d5c 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -37,13 +37,16 @@ * @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 @@ -52,6 +55,8 @@ extern "C" { GHandle gwinListCreate(GListObject *widget, GWidgetInit *pInit); +int gwinListAddItem(GHandle gh, const char* item, bool_t useAlloc); + #ifdef __cplusplus } #endif diff --git a/src/gwin/list.c b/src/gwin/list.c index eae9bb46..bfb341af 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -20,11 +20,106 @@ #if GFX_USE_GWIN && GWIN_NEED_LIST #include "gwin/class_gwin.h" +#include + +#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) + +/* +Use gw->pstyle->background for the unselected fill. +Use gw->pstyle->enabled/disabled->text for unselected text color +Use gw->pstyle->enabled/disabled->edge for the surounding box +Use gw->pstyle->enabled/disabled->fill for the selected text fill +or gw->pstyle->pressed->fill for the selected text fill (which ever looks best) +and use gw->pstyle->pressed->text for the selected text color +*/ + +typedef struct ListItem { + gfxQueueASyncItem q_item; // This must be the first member in the struct + + uint16_t id; + uint16_t flags; + #define LISTITEM_ALLOCEDTEXT 0x0001 + #define LISTITEM_SELECTED 0x0002 + uint16_t uparam; + const char* text; + #if GWIN_LIST_IMAGES + gdispImage* pimg; + #endif +} ListItem; + +static void sendListEvent(GWidgetObject *gw) { + 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_SLIDER; + pse->list = (GHandle)gw; + pse->item = 42; + + geventSendEvent(psl); + } + + #undef pse +} static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { + #define gcw ((GListObject *)gw) + (void)param; + uint16_t i, fheight; + gfxQueueASyncItem* qi; + + fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight); + + gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, Black); + + for (qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i += fheight + 4) { + if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) + gdispFillStringBox(gw->g.x + 3, gw->g.y + 3 + i, gw->g.width - 6, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), White, Black, justifyLeft); + else + gdispFillStringBox(gw->g.x + 3, gw->g.y + 3 + i, gw->g.width - 6, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), Black, White, 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) + + uint16_t i, item_id, item_height; + gfxQueueASyncItem* qi; + + item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2; + + item_id = (y - gw->g.y) / item_height; + printf("item_id = %d\r\n", item_id); + + for(qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (item_id == i) + ((ListItem*)qi)->flags |= GLIST_FLG_SELECTED; + else + ((ListItem*)qi)->flags &=~ GLIST_FLG_SELECTED; + } + + _gwidgetRedraw((GHandle)gw); + sendListEvent(gw); + + #undef gcw + } +#endif + static const gwidgetVMT listVMT = { { "List", // The class name @@ -34,9 +129,9 @@ static const gwidgetVMT listVMT = { 0, // The after-clear routine }, gwinListDefaultDraw, // default drawing routine - #if GWINPUT_NEED_MOUSE + #if GINPUT_NEED_MOUSE { - 0, + MouseDown, 0, 0, }, @@ -64,11 +159,55 @@ 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) { + ListItem* newItem; + + if (useAlloc) { + newItem = gfxAlloc(sizeof(newItem) + strlen(item_name) + 1); + + // allocate string + newItem->text = gfxAlloc(strlen(item_name) + 1); + if (newItem->text == NULL) + return -1; + + // assign text + newItem->text = item_name; + + } else { + newItem = gfxAlloc(sizeof(newItem)); + + if (newItem == NULL) + return -1; + } + + // the item is not selected when added + 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++; +} + +int gwinListGetSelected(GHandle gh) { + gfxQueueASyncItem* qi; + uint16_t i; + + //for(qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + + +} + #endif // GFX_USE_GWIN && GWIN_NEED_LIST /** @} */ From 9dfcbef84884f67bb487dc02c642a03ca5d19e32 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sat, 27 Jul 2013 15:23:52 +0200 Subject: [PATCH 02/18] list work in progress --- src/gwin/list.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/gwin/list.c b/src/gwin/list.c index bfb341af..cc7c40f4 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -40,17 +40,28 @@ and use gw->pstyle->pressed->text for the selected text color typedef struct ListItem { gfxQueueASyncItem q_item; // This must be the first member in the struct - uint16_t id; uint16_t flags; #define LISTITEM_ALLOCEDTEXT 0x0001 #define LISTITEM_SELECTED 0x0002 - uint16_t uparam; + uint16_t param; // A parameter the user can specify himself const char* text; #if GWIN_LIST_IMAGES gdispImage* pimg; #endif } ListItem; +static int _getSelected(GWidgetObject *gw) { + gfxQueueASyncItem* qi; + uint16_t i; + + for(qi = gfxQueueASyncPeek(&((GListObject*)gw)->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) + return i; + } + + return -1; +} + static void sendListEvent(GWidgetObject *gw) { GSourceListener* psl; GEvent* pe; @@ -58,17 +69,18 @@ static void sendListEvent(GWidgetObject *gw) { // Trigger a GWIN list event psl = 0; + while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { if (!(pe = geventGetEventBuffer(psl))) continue pse->type = GEVENT_GWIN_SLIDER; pse->list = (GHandle)gw; - pse->item = 42; + pse->item = _getSelected(gw); geventSendEvent(psl); } - + #undef pse } @@ -104,7 +116,6 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2; item_id = (y - gw->g.y) / item_height; - printf("item_id = %d\r\n", item_id); for(qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { if (item_id == i) From 1fbbc4d52bed0b8e4f3289bc008b3f0928a6b24f Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 27 Jul 2013 22:25:20 +1000 Subject: [PATCH 03/18] Integrate changes from master branch --- demos/modules/gwin/widgets/gfxconf.h | 2 +- include/gos/osx.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h index fffe685d..f8d8fe5f 100644 --- a/demos/modules/gwin/widgets/gfxconf.h +++ b/demos/modules/gwin/widgets/gfxconf.h @@ -29,7 +29,7 @@ #ifndef _GFXCONF_H #define _GFXCONF_H -#define GFX_USE_OS_CHIBIOS TRUE +//#define GFX_USE_OS_CHIBIOS TRUE //#define GFX_USE_OS_WIN32 TRUE //#define GFX_USE_OS_POSIX TRUE diff --git a/include/gos/osx.h b/include/gos/osx.h index 2ba1c45d..3f36aaff 100644 --- a/include/gos/osx.h +++ b/include/gos/osx.h @@ -48,7 +48,6 @@ typedef pthread_mutex_t gfxMutex; #define gfxSemSignalI(psem) gfxSemSignal(psem) #define gfxSemCounterI(pSem) ((pSem)->cnt) -#define TRUE 1 #define TIME_IMMEDIATE 0 #define TIME_INFINITE ((delaytime_t)-1) #define MAX_SEMAPHORE_COUNT ((semcount_t)-1) From 984e14efb7ad257577db85fcdbed6c60618c1175 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 27 Jul 2013 22:26:16 +1000 Subject: [PATCH 04/18] List updates and add list demo - still work in progress --- demos/modules/gwin/list/gfxconf.h | 150 ++++++++++++++++++++++++++++++ demos/modules/gwin/list/main.c | 63 +++++++++++++ src/gwin/list.c | 90 +++++++++--------- 3 files changed, 259 insertions(+), 44 deletions(-) create mode 100644 demos/modules/gwin/list/gfxconf.h create mode 100644 demos/modules/gwin/list/main.c 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/src/gwin/list.c b/src/gwin/list.c index cc7c40f4..11fd01cb 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -50,19 +50,7 @@ typedef struct ListItem { #endif } ListItem; -static int _getSelected(GWidgetObject *gw) { - gfxQueueASyncItem* qi; - uint16_t i; - - for(qi = gfxQueueASyncPeek(&((GListObject*)gw)->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { - if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) - return i; - } - - return -1; -} - -static void sendListEvent(GWidgetObject *gw) { +static void sendListEvent(GWidgetObject *gw, int item) { GSourceListener* psl; GEvent* pe; #define pse ((GEventGWinList *)pe) @@ -72,11 +60,11 @@ static void sendListEvent(GWidgetObject *gw) { while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { if (!(pe = geventGetEventBuffer(psl))) - continue + continue; - pse->type = GEVENT_GWIN_SLIDER; + pse->type = GEVENT_GWIN_LIST; pse->list = (GHandle)gw; - pse->item = _getSelected(gw); + pse->item = item; geventSendEvent(psl); } @@ -89,7 +77,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { (void)param; uint16_t i, fheight; - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight); @@ -109,9 +97,11 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { // 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; - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2; @@ -119,23 +109,32 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { for(qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { if (item_id == i) - ((ListItem*)qi)->flags |= GLIST_FLG_SELECTED; + li->flags |= GLIST_FLG_SELECTED; else - ((ListItem*)qi)->flags &=~ GLIST_FLG_SELECTED; + li->flags &=~ GLIST_FLG_SELECTED; } _gwidgetRedraw((GHandle)gw); - sendListEvent(gw); + sendListEvent(gw, item_id); #undef gcw + #undef li } #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 }, @@ -180,43 +179,46 @@ GHandle gwinListCreate(GListObject* widget, GWidgetInit* pInit) { } int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { - ListItem* newItem; + size_t sz; + ListItem *newItem; + + sz = useAlloc ? sizeof(ListItem)+strlen(item_name)+1 : sizeof(ListItem); + + if (!(newItem = (ListItem *)gfxAlloc(sz))) + return -1; if (useAlloc) { - newItem = gfxAlloc(sizeof(newItem) + strlen(item_name) + 1); - - // allocate string - newItem->text = gfxAlloc(strlen(item_name) + 1); - if (newItem->text == NULL) - return -1; - - // assign text - newItem->text = item_name; - - } else { - newItem = gfxAlloc(sizeof(newItem)); - - if (newItem == NULL) - return -1; + strcpy((char *)(newItem+1), item_name); + item_name = (const char *)(newItem+1); } // the item is not selected when added - newItem->flags &=~ GLIST_FLG_SELECTED; + newItem->flags = 0; + newItem->param = 0; + newItem->text = item_name; // add the new item to the list - gfxQueueASyncPut(&(widget(gh)->list_head), &newItem->q_item); + gfxQueueASyncPut(&widget(gh)->list_head, &newItem->q_item); // increment the total amount of entries in the list widget widget(gh)->cnt++; + + return widget(gh)->cnt-1; } int gwinListGetSelected(GHandle gh) { - gfxQueueASyncItem* qi; - uint16_t i; + const gfxQueueASyncItem *qi; + int i; - //for(qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + 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; } #endif // GFX_USE_GWIN && GWIN_NEED_LIST From 40611e264d9fc8b05db05ec4dc410e919af7f98d Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sat, 27 Jul 2013 22:55:32 +0200 Subject: [PATCH 05/18] some more list work --- include/gwin/list.h | 18 +++++ src/gwin/list.c | 177 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 185 insertions(+), 10 deletions(-) diff --git a/include/gwin/list.h b/include/gwin/list.h index 46e32d5c..307226c9 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -57,6 +57,24 @@ GHandle gwinListCreate(GListObject *widget, GWidgetInit *pInit); int gwinListAddItem(GHandle gh, const char* item, bool_t useAlloc); +char* gwinListItemGetText(GHandle gh, int item); + +int gwinListFindText(GHandle gh, const char* text); + +void gwinListItemSetParam(GHandle gh, int item, uint16_t param); + +uint16_t gwinListItemGetParam(GHandle gh, int item); + +void nListDeleteAll(GHandle gh); + +void gwinListItemDelete(GHandle gh, int item); + +int gwinListItemCount(GHandle gh); + +bool_t gwinListItemIsSelected(GHandle gh, int item); + +int gwinListGetSelected(GHandle gh); + #ifdef __cplusplus } #endif diff --git a/src/gwin/list.c b/src/gwin/list.c index 11fd01cb..9b9ab7c6 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -22,6 +22,8 @@ #include "gwin/class_gwin.h" #include +#define BORDER 3 + #define widget(gh) ((GListObject *)gh) #define GLIST_FLG_MULTISELECT (GWIN_FIRST_CONTROL_FLAG << 0) @@ -42,7 +44,6 @@ typedef struct ListItem { uint16_t flags; #define LISTITEM_ALLOCEDTEXT 0x0001 - #define LISTITEM_SELECTED 0x0002 uint16_t param; // A parameter the user can specify himself const char* text; #if GWIN_LIST_IMAGES @@ -77,17 +78,18 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { (void)param; uint16_t i, fheight; - const gfxQueueASyncItem* qi; + gfxQueueASyncItem* qi; + const GColorSet* pcol; fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight); gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, Black); - for (qi = gfxQueueASyncPeek(&gcw->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i += fheight + 4) { + 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 + 3, gw->g.y + 3 + i, gw->g.width - 6, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), White, Black, justifyLeft); + gdispFillStringBox(gw->g.x + BORDER, gw->g.y + BORDER + i, gw->g.width - 2*BORDER, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), White, Black, justifyLeft); else - gdispFillStringBox(gw->g.x + 3, gw->g.y + 3 + i, gw->g.width - 6, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), Black, White, justifyLeft); + gdispFillStringBox(gw->g.x + BORDER, gw->g.y + BORDER + i, gw->g.width - 2*BORDER, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), Black, White, justifyLeft); } #undef gcw @@ -101,9 +103,9 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { (void) x; uint16_t i, item_id, item_height; - const gfxQueueASyncItem* qi; + gfxQueueASyncItem* qi; - item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2; + item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2*BORDER; item_id = (y - gw->g.y) / item_height; @@ -115,6 +117,11 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { } _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 @@ -123,10 +130,11 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { #endif static void _destroy(GHandle gh) { - const gfxQueueASyncItem* qi; + gfxQueueASyncItem* qi; while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) gfxFree((void *)qi); + _gwidgetDestroy(gh); } @@ -134,7 +142,7 @@ static const gwidgetVMT listVMT = { { "List", // The class name sizeof(GListObject), // The object size - _destroy, // The destroy routine + _destroy, // The destroy routine _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, @@ -203,13 +211,58 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { // 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) { + 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) { + 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; + gfxQueueASyncItem *qi; int i; + // is it a valid handle? if (gh->vmt != (gwinVMT *)&listVMT) return -1; @@ -221,6 +274,110 @@ int gwinListGetSelected(GHandle gh) { return -1; } +void gwinListItemSetParam(GHandle gh, int item, uint16_t param) { + 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) { + gfxQueueASyncItem* qi; + + while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) + gfxFree((void *)qi); +} + +void gwinListItemDelete(GHandle gh, int item) { + 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) { + 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) { + 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 /** @} */ From 9edb1dab8b176a1f7e229709dcd5e7bca75a0890 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 01:15:36 +0200 Subject: [PATCH 06/18] compiler warnings --- src/gwin/list.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/gwin/list.c b/src/gwin/list.c index 9b9ab7c6..8e1f2ef4 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -78,7 +78,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { (void)param; uint16_t i, fheight; - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; const GColorSet* pcol; fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight); @@ -103,7 +103,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { (void) x; uint16_t i, item_id, item_height; - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2*BORDER; @@ -130,7 +130,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { #endif static void _destroy(GHandle gh) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) gfxFree((void *)qi); @@ -216,7 +216,7 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { } char* gwinListItemGetText(GHandle gh, int item) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; uint16_t i; // is it a valid handle? @@ -237,7 +237,7 @@ char* gwinListItemGetText(GHandle gh, int item) { } int gwinListFindText(GHandle gh, const char* text) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; uint16_t i; // is it a valid handle? @@ -259,7 +259,7 @@ int gwinListFindText(GHandle gh, const char* text) { } int gwinListGetSelected(GHandle gh) { - gfxQueueASyncItem *qi; + const gfxQueueASyncItem *qi; int i; // is it a valid handle? @@ -275,7 +275,7 @@ int gwinListGetSelected(GHandle gh) { } void gwinListItemSetParam(GHandle gh, int item, uint16_t param) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; uint16_t i; // is it a valid handle? @@ -296,14 +296,14 @@ void gwinListItemSetParam(GHandle gh, int item, uint16_t param) { } void gwinListDeleteAll(GHandle gh) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) gfxFree((void *)qi); } void gwinListItemDelete(GHandle gh, int item) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; uint16_t i; // is it a valid handle? @@ -326,7 +326,7 @@ void gwinListItemDelete(GHandle gh, int item) { } uint16_t gwinListItemGetParam(GHandle gh, int item) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; uint16_t i; // is it a valid handle? @@ -347,7 +347,7 @@ uint16_t gwinListItemGetParam(GHandle gh, int item) { } bool_t gwinListItemIsSelected(GHandle gh, int item) { - gfxQueueASyncItem* qi; + const gfxQueueASyncItem* qi; uint16_t i; // is it a valid handle? From c7fdb5df2a32e21905e21193bc018c5d6fc6d326 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 02:06:27 +0200 Subject: [PATCH 07/18] list widget first implementation --- src/gwin/list.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gwin/list.c b/src/gwin/list.c index 8e1f2ef4..1d61f1c4 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -79,17 +79,17 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { uint16_t i, fheight; const gfxQueueASyncItem* qi; - const GColorSet* pcol; fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight); - gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, Black); + gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, 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, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), White, Black, justifyLeft); - else - gdispFillStringBox(gw->g.x + BORDER, gw->g.y + BORDER + i, gw->g.width - 2*BORDER, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), Black, White, justifyLeft); + if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) { + gdispFillStringBox(gw->g.x + BORDER, gw->g.y + BORDER + i, gw->g.width - 2*BORDER, 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, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), gw->pstyle->enabled.text, gw->pstyle->background, justifyLeft); + } } #undef gcw From 4e3eacb9f762addc6049e28d39516724ef1beef8 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 03:31:45 +0200 Subject: [PATCH 08/18] list widget doxygen --- include/gwin/list.h | 122 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/include/gwin/list.h b/include/gwin/list.h index 307226c9..7355623f 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -53,26 +53,146 @@ typedef struct GListObject { 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. Three roles are supported: + * Role 0 = toggle for down, role 1 = toggle for up, role 2 = toggle for select. + * @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); -void nListDeleteAll(GHandle gh); +/** + * @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 From c66e5cd9cbcdea293d661c6886587b3c9ca35078 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 07:00:08 +0200 Subject: [PATCH 09/18] some more list widget work --- src/gwin/list.c | 109 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 20 deletions(-) diff --git a/src/gwin/list.c b/src/gwin/list.c index 1d61f1c4..8f5530a2 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -22,7 +22,10 @@ #include "gwin/class_gwin.h" #include -#define BORDER 3 +// 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) @@ -30,20 +33,10 @@ #define GLIST_FLG_HASIMAGES (GWIN_FIRST_CONTROL_FLAG << 1) #define GLIST_FLG_SELECTED (GWIN_FIRST_CONTROL_FLAG << 2) -/* -Use gw->pstyle->background for the unselected fill. -Use gw->pstyle->enabled/disabled->text for unselected text color -Use gw->pstyle->enabled/disabled->edge for the surounding box -Use gw->pstyle->enabled/disabled->fill for the selected text fill -or gw->pstyle->pressed->fill for the selected text fill (which ever looks best) -and use gw->pstyle->pressed->text for the selected text color -*/ - typedef struct ListItem { gfxQueueASyncItem q_item; // This must be the first member in the struct uint16_t flags; - #define LISTITEM_ALLOCEDTEXT 0x0001 uint16_t param; // A parameter the user can specify himself const char* text; #if GWIN_LIST_IMAGES @@ -51,6 +44,41 @@ typedef struct ListItem { #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 _selectEnter(GWidgetObject *gw) { + #define gcw ((GListObject *)gw) + + + + #undef gcw +} + static void sendListEvent(GWidgetObject *gw, int item) { GSourceListener* psl; GEvent* pe; @@ -78,17 +106,29 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { (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, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), gw->pstyle->background, gw->pstyle->enabled.text, justifyLeft); + 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, fheight, ((ListItem*)qi)->text, gwinGetDefaultFont(), gw->pstyle->enabled.text, gw->pstyle->background, justifyLeft); + 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); } } @@ -96,7 +136,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { } #if GINPUT_NEED_MOUSE - // A mouse down has occured over the list area + // 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) @@ -106,7 +146,6 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { 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++) { @@ -118,7 +157,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { _gwidgetRedraw((GHandle)gw); - // Do not generate an event if an empty section of the list has has been selected + // 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; @@ -129,6 +168,32 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { } #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; + + // select enter + case 2: + _selectEnter(gw); + break; + } + + #undef gcw + } +#endif + static void _destroy(GHandle gh) { const gfxQueueASyncItem* qi; @@ -156,11 +221,11 @@ static const gwidgetVMT listVMT = { #endif #if GINPUT_NEED_TOGGLE { + 2, // three toggle roles + ToggleAssin, // Assign toggles + ToggleGet, // get toggles 0, - 0, - 0, - 0, - 0, + ToggleOn, // process toggle on event }, #endif #if GINPUT_NEED_DIAL @@ -205,6 +270,10 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { 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); From 423c28b40e0849838615e575630d8e251f04739b Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 07:04:04 +0200 Subject: [PATCH 10/18] cleanup --- include/gwin/list.h | 4 ++-- src/gwin/list.c | 15 +-------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/include/gwin/list.h b/include/gwin/list.h index 7355623f..ba83f24b 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -65,8 +65,8 @@ extern "C" { * @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. Three roles are supported: - * Role 0 = toggle for down, role 1 = toggle for up, role 2 = toggle for select. + * 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. * diff --git a/src/gwin/list.c b/src/gwin/list.c index 8f5530a2..f495ada4 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -71,14 +71,6 @@ static void _selectDown(GWidgetObject *gw) { #undef gcw } -static void _selectEnter(GWidgetObject *gw) { - #define gcw ((GListObject *)gw) - - - - #undef gcw -} - static void sendListEvent(GWidgetObject *gw, int item) { GSourceListener* psl; GEvent* pe; @@ -183,11 +175,6 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { case 1: _selectDown(gw); break; - - // select enter - case 2: - _selectEnter(gw); - break; } #undef gcw @@ -221,7 +208,7 @@ static const gwidgetVMT listVMT = { #endif #if GINPUT_NEED_TOGGLE { - 2, // three toggle roles + 2, // two toggle roles ToggleAssin, // Assign toggles ToggleGet, // get toggles 0, From 580cf977d07820774efd8abcf067f015422b7e55 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 14:13:05 +0200 Subject: [PATCH 11/18] clear after mouse calibration to avoid silly display --- src/ginput/mouse.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c index 28707d8b..5459a4cd 100644 --- a/src/ginput/mouse.c +++ b/src/ginput/mouse.c @@ -509,6 +509,13 @@ bool_t ginputCalibrateMouse(uint16_t instance) { MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata)); MouseConfig.flags |= FLG_CAL_SAVED; } + + // Clear the screen using the GWIN default background color + #if GFX_USE_GWIN + gdispClear(gwinGetDefaultBgColor()); + #else + gdispClear(White); + #endif return TRUE; #endif From 632566e243e1fa914dfee6ec87913d940856963c Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 15:26:59 +0200 Subject: [PATCH 12/18] list fix --- src/gwin/list.c | 53 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/gwin/list.c b/src/gwin/list.c index f495ada4..54bac334 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -44,7 +44,8 @@ typedef struct ListItem { #endif } ListItem; -void _selectUp(GWidgetObject *gw) { +// select the next item in the list +static int _selectDown(GWidgetObject *gw) { #define gcw ((GListObject *)gw) gfxQueueASyncItem *qi; @@ -55,19 +56,44 @@ void _selectUp(GWidgetObject *gw) { ((ListItem*)qi)->flags &=~ GLIST_FLG_SELECTED; qi = gfxQueueASyncNext(qi); ((ListItem*)qi)->flags |= GLIST_FLG_SELECTED; + + break; } } _gwidgetRedraw((GHandle)gw); + return ++i; + #undef gcw } -static void _selectDown(GWidgetObject *gw) { +// select the previous item in the list +static int _selectUp(GWidgetObject *gw) { #define gcw ((GListObject *)gw) + gfxQueueASyncItem *qi; + gfxQueueASyncItem *qi2; + uint16_t i; + + qi = gfxQueueASyncPeek(&gcw->list_head); + qi2 = qi; + + for (i = 0; qi2; qi2 = gfxQueueASyncNext(qi), i++) { + if (((ListItem*)qi2)->flags & GLIST_FLG_SELECTED) { + ((ListItem*)qi2)->flags &=~ GLIST_FLG_SELECTED; + ((ListItem*)qi)->flags |= GLIST_FLG_SELECTED; + + break; + } + + qi = qi2; + } + _gwidgetRedraw((GHandle)gw); + return --i; + #undef gcw } @@ -137,14 +163,23 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { 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; + item_id = -1; - 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; + if (x > gw->g.width - BORDER_SCROLL) { + if (y < BORDER_SCROLL) + item_id = _selectUp(gw); + else if (y > gw->g.height - BORDER_SCROLL) + item_id = _selectDown(gw); + } else if (x < gw->g.width - BORDER_SCROLL - BORDER) { + item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2*BORDER; + item_id = (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); From 31f355460248b2d39969590feefc9482e53c451f Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Sun, 28 Jul 2013 23:18:59 +0200 Subject: [PATCH 13/18] list update --- include/gwin/list.h | 6 ++++++ src/gwin/list.c | 21 ++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/gwin/list.h b/include/gwin/list.h index ba83f24b..d28206d9 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -45,6 +45,12 @@ typedef struct GEventGWinList { // A list window typedef struct GListObject { GWidgetObject w; + + #if GINPUT_NEED_TOGGLE + uint16_t t_up; + uint16_t t_dn; + #endif + int cnt; // Number of items currently in the list (quicker than counting each time) gfxQueueASync list_head; // The list of items } GListObject; diff --git a/src/gwin/list.c b/src/gwin/list.c index 54bac334..2509260c 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -201,19 +201,30 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { #define gcw ((GListObject *)gw) switch (role) { - // select up + // select down case 0: - _selectUp(gw); + _selectDown(gw); break; - // select down + // select up case 1: - _selectDown(gw); + _selectUp(gw); break; } #undef gcw } + + static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) { + if (role) + ((GListObject *)gw)->t_up = instance; + else + ((GListObject *)gw)->t_dn = instance; + } + + static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) { + return role ? ((GListObject *)gw)->t_up : ((GListObject *)gw)->t_dn; + } #endif static void _destroy(GHandle gh) { @@ -244,7 +255,7 @@ static const gwidgetVMT listVMT = { #if GINPUT_NEED_TOGGLE { 2, // two toggle roles - ToggleAssin, // Assign toggles + ToggleAssign, // Assign toggles ToggleGet, // get toggles 0, ToggleOn, // process toggle on event From 06d339456e64f6257bd72eb9343d7c899ea0b20b Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 14:50:40 +1000 Subject: [PATCH 14/18] Update gwin widgets and lists demos --- demos/modules/gwin/list/gfxconf.h | 2 +- demos/modules/gwin/list/main.c | 29 +++++++++++++-------- demos/modules/gwin/widgets/gfxconf.h | 1 + demos/modules/gwin/widgets/main.c | 38 +++++++++++++++++++++++++--- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/demos/modules/gwin/list/gfxconf.h b/demos/modules/gwin/list/gfxconf.h index 895d7c49..cf5f8690 100644 --- a/demos/modules/gwin/list/gfxconf.h +++ b/demos/modules/gwin/list/gfxconf.h @@ -40,7 +40,7 @@ #define GDISP_NEED_CIRCLE TRUE #define GDISP_NEED_ELLIPSE TRUE #define GDISP_NEED_ARC FALSE -#define GDISP_NEED_CONVEX_POLYGON FALSE +#define GDISP_NEED_CONVEX_POLYGON TRUE #define GDISP_NEED_SCROLL FALSE #define GDISP_NEED_PIXELREAD FALSE #define GDISP_NEED_CONTROL FALSE diff --git a/demos/modules/gwin/list/main.c b/demos/modules/gwin/list/main.c index 35847be0..a3a17250 100644 --- a/demos/modules/gwin/list/main.c +++ b/demos/modules/gwin/list/main.c @@ -10,11 +10,11 @@ static void createWidgets(void) { wi.customDraw = 0; wi.customParam = 0; wi.customStyle = 0; - wi.g.show = TRUE; + wi.g.show = FALSE; // Apply the list parameters - wi.g.width = 300; - wi.g.height = 200; + wi.g.width = 100; + wi.g.height = 80; wi.g.y = 10; wi.g.x = 10; wi.text = "List Name"; @@ -32,7 +32,7 @@ int main(void) { // Set the widget defaults gwinSetDefaultFont(gdispOpenFont("UI2")); gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE); - gdispClear(White); + gdispClear(Red); // Attach the mouse input gwinAttachMouse(0); @@ -45,13 +45,22 @@ int main(void) { 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); + gwinListAddItem(ghList1, "Item 0", FALSE); + gwinListAddItem(ghList1, "Item 1", FALSE); + gwinListAddItem(ghList1, "Item 2", FALSE); + gwinListAddItem(ghList1, "Item 3", FALSE); + gwinListAddItem(ghList1, "Item 4", FALSE); + gwinListAddItem(ghList1, "Item 5", FALSE); + gwinListAddItem(ghList1, "Item 6", FALSE); + gwinListAddItem(ghList1, "Item 7", FALSE); + gwinListAddItem(ghList1, "Item 8", FALSE); + gwinListAddItem(ghList1, "Item 9", FALSE); + gwinListAddItem(ghList1, "Item 10", FALSE); + gwinListAddItem(ghList1, "Item 11", FALSE); + gwinListAddItem(ghList1, "Item 12", FALSE); + gwinListAddItem(ghList1, "Item 13", FALSE); - gwinRedraw(ghList1); + gwinSetVisible(ghList1, TRUE); while(1) { // Get an Event diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h index f8d8fe5f..10db7bbc 100644 --- a/demos/modules/gwin/widgets/gfxconf.h +++ b/demos/modules/gwin/widgets/gfxconf.h @@ -81,6 +81,7 @@ #define GWIN_NEED_LABEL TRUE #define GWIN_NEED_IMAGE TRUE #define GWIN_NEED_RADIO TRUE +#define GWIN_NEED_LIST TRUE #define GWIN_NEED_IMAGE_ANIMATION TRUE diff --git a/demos/modules/gwin/widgets/main.c b/demos/modules/gwin/widgets/main.c index bff842f4..f2323b5c 100644 --- a/demos/modules/gwin/widgets/main.c +++ b/demos/modules/gwin/widgets/main.c @@ -69,13 +69,14 @@ static const GWidgetStyle YellowWidgetStyle = { /* The variables we need */ static GListener gl; static GHandle ghConsole; -static GHandle ghTabButtons, ghTabSliders, ghTabCheckboxes, ghTabLabels, ghTabRadios, ghTabImages; +static GHandle ghTabButtons, ghTabSliders, ghTabCheckboxes, ghTabLabels, ghTabRadios, ghTabLists, ghTabImages; static GHandle ghButton1, ghButton2, ghButton3, ghButton4; static GHandle ghSlider1, ghSlider2, ghSlider3, ghSlider4; static GHandle ghCheckbox1, ghCheckbox2, ghCheckDisableAll; static GHandle ghLabel1; static GHandle ghRadio1, ghRadio2; static GHandle ghRadioBlack, ghRadioWhite, ghRadioYellow; +static GHandle ghList1; static GHandle ghImage1; /* Some useful macros */ @@ -86,6 +87,8 @@ static GHandle ghImage1; #define LABEL_HEIGHT 40 #define BUTTON_WIDTH 50 #define BUTTON_HEIGHT 30 +#define LIST_WIDTH 100 +#define LIST_HEIGHT 80 #define SLIDER_WIDTH 20 #define CHECKBOX_WIDTH 80 #define CHECKBOX_HEIGHT 20 @@ -108,13 +111,14 @@ static void createWidgets(void) { // Create the Tabs wi.g.show = TRUE; wi.customDraw = gwinRadioDraw_Tab; - wi.g.width = ScrWidth/6; wi.g.height = TAB_HEIGHT; wi.g.y = 0; + wi.g.width = ScrWidth/7; wi.g.height = TAB_HEIGHT; wi.g.y = 0; wi.g.x = 0*wi.g.width; wi.text = "Buttons"; ghTabButtons = gwinRadioCreate(NULL, &wi, GROUP_TABS); wi.g.x = 1*wi.g.width; wi.text = "Sliders"; ghTabSliders = gwinRadioCreate(NULL, &wi, GROUP_TABS); wi.g.x = 2*wi.g.width; wi.text = "Checkbox"; ghTabCheckboxes = gwinRadioCreate(NULL, &wi, GROUP_TABS); wi.g.x = 3*wi.g.width; wi.text = "Radios"; ghTabRadios = gwinRadioCreate(NULL, &wi, GROUP_TABS); - wi.g.x = 4*wi.g.width; wi.text = "Labels"; ghTabLabels = gwinRadioCreate(NULL, &wi, GROUP_TABS); - wi.g.x = 5*wi.g.width; wi.text = "Images"; ghTabImages = gwinRadioCreate(NULL, &wi, GROUP_TABS); + wi.g.x = 4*wi.g.width; wi.text = "Lists"; ghTabLists = gwinRadioCreate(NULL, &wi, GROUP_TABS); + wi.g.x = 5*wi.g.width; wi.text = "Labels"; ghTabLabels = gwinRadioCreate(NULL, &wi, GROUP_TABS); + wi.g.x = 6*wi.g.width; wi.text = "Images"; ghTabImages = gwinRadioCreate(NULL, &wi, GROUP_TABS); // Buttons wi.g.show = FALSE; wi.customDraw = 0; @@ -156,6 +160,25 @@ static void createWidgets(void) { wi.g.x = 2*wi.g.width; wi.text = "Yellow"; ghRadioYellow = gwinRadioCreate(NULL, &wi, GROUP_COLORS); gwinRadioPress(ghRadioWhite); + // Lists + wi.g.show = FALSE; wi.customDraw = 0; + wi.g.width = LIST_WIDTH; wi.g.height = LIST_HEIGHT; wi.g.y = TAB_HEIGHT+5; + wi.g.x = 0+0*(LIST_WIDTH+1); wi.text = "L1"; ghList1 = gwinListCreate(NULL, &wi); + gwinListAddItem(ghList1, "Item 0", FALSE); + gwinListAddItem(ghList1, "Item 1", FALSE); + gwinListAddItem(ghList1, "Item 2", FALSE); + gwinListAddItem(ghList1, "Item 3", FALSE); + gwinListAddItem(ghList1, "Item 4", FALSE); + gwinListAddItem(ghList1, "Item 5", FALSE); + gwinListAddItem(ghList1, "Item 6", FALSE); + gwinListAddItem(ghList1, "Item 7", FALSE); + gwinListAddItem(ghList1, "Item 8", FALSE); + gwinListAddItem(ghList1, "Item 9", FALSE); + gwinListAddItem(ghList1, "Item 10", FALSE); + gwinListAddItem(ghList1, "Item 11", FALSE); + gwinListAddItem(ghList1, "Item 12", FALSE); + gwinListAddItem(ghList1, "Item 13", FALSE); + // Image wi.g.x = ScrWidth-210; wi.g.y = TAB_HEIGHT + 10; wi.g.width = 200; wi.g.height = 200; ghImage1 = gwinImageCreate(NULL, &wi.g); @@ -183,6 +206,7 @@ static void setTab(GHandle tab) { gwinSetVisible(ghLabel1, FALSE); gwinSetVisible(ghRadio1, FALSE); gwinSetVisible(ghRadio2, FALSE); gwinSetVisible(ghRadioWhite, FALSE);gwinSetVisible(ghRadioBlack, FALSE);gwinSetVisible(ghRadioYellow, FALSE); + gwinSetVisible(ghList1, FALSE); gwinSetVisible(ghImage1, FALSE); /* Turn on widgets depending on the tab selected */ @@ -199,6 +223,8 @@ static void setTab(GHandle tab) { } else if (tab == ghTabRadios) { gwinSetVisible(ghRadio1, TRUE); gwinSetVisible(ghRadio2, TRUE); gwinSetVisible(ghRadioWhite, TRUE); gwinSetVisible(ghRadioBlack, TRUE); gwinSetVisible(ghRadioYellow, TRUE); + } else if (tab == ghTabLists) { + gwinSetVisible(ghList1, TRUE); } else if (tab == ghTabImages) { gwinSetVisible(ghImage1, TRUE); } @@ -282,6 +308,10 @@ int main(void) { } break; + case GEVENT_GWIN_LIST: + gwinPrintf(ghConsole, "List %s Item %d\n", gwinGetText(((GEventGWinList *)pe)->list), ((GEventGWinList *)pe)->item); + break; + case GEVENT_GWIN_RADIO: gwinPrintf(ghConsole, "Radio Group %u=%s\n", ((GEventGWinRadio *)pe)->group, gwinGetText(((GEventGWinRadio *)pe)->radio)); From 2d27673f0f45a1b96aa7b9d8de61807fadb020bc Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 14:51:40 +1000 Subject: [PATCH 15/18] Update GWIN widget demo --- demos/modules/gwin/widgets/gfxconf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h index 10db7bbc..9ca5580b 100644 --- a/demos/modules/gwin/widgets/gfxconf.h +++ b/demos/modules/gwin/widgets/gfxconf.h @@ -47,7 +47,7 @@ #define GDISP_NEED_CIRCLE TRUE #define GDISP_NEED_ELLIPSE FALSE #define GDISP_NEED_ARC FALSE -#define GDISP_NEED_CONVEX_POLYGON FALSE +#define GDISP_NEED_CONVEX_POLYGON TRUE #define GDISP_NEED_SCROLL FALSE #define GDISP_NEED_PIXELREAD FALSE #define GDISP_NEED_CONTROL FALSE From 9d2b0b667b9bfb2d8b6969ade0ff0bd8d646d7d7 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 14:52:28 +1000 Subject: [PATCH 16/18] Add color blending to GDISP --- include/gdisp/gdisp.h | 13 +++++++++++++ src/gdisp/gdisp.c | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/gdisp/gdisp.h b/include/gdisp/gdisp.h index ac741d3b..ca1844fd 100644 --- a/include/gdisp/gdisp.h +++ b/include/gdisp/gdisp.h @@ -800,6 +800,19 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color); #endif + +/** + * @brief Blend 2 colors according to the alpha + * @return The combined color + * + * @param[in] fg The foreground color + * @param[in] bg The background color + * @param[in] alpha The alpha value (0-255). 0 is all background, 255 is all foreground. + * + * @api + */ +color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha); + /* Support routine for packed pixel formats */ #if !defined(gdispPackPixels) || defined(__DOXYGEN__) /** diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 4c005079..b59b571d 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -990,6 +990,27 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { } #endif +color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha) +{ + uint16_t fg_ratio = alpha + 1; + uint16_t bg_ratio = 256 - alpha; + uint16_t r, g, b; + + r = RED_OF(fg) * fg_ratio; + g = GREEN_OF(fg) * fg_ratio; + b = BLUE_OF(fg) * fg_ratio; + + r += RED_OF(bg) * bg_ratio; + g += GREEN_OF(bg) * bg_ratio; + b += BLUE_OF(bg) * bg_ratio; + + r /= 256; + g /= 256; + b /= 256; + + return RGB2COLOR(r, g, b); +} + #if (!defined(gdispPackPixels) && !defined(GDISP_PIXELFORMAT_CUSTOM)) void gdispPackPixels(pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color) { /* No mutex required as we only read static data */ From 58b52600138435073803de6844b4adb48b501307 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 14:53:13 +1000 Subject: [PATCH 17/18] Update some GQUEUE prototypes --- include/gqueue/gqueue.h | 6 +++--- src/gqueue/gqueue.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/gqueue/gqueue.h b/include/gqueue/gqueue.h index 44a42247..b590846c 100644 --- a/include/gqueue/gqueue.h +++ b/include/gqueue/gqueue.h @@ -206,9 +206,9 @@ bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue); * @api * @{ */ -bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); -bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); -bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); +bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem); +bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem); +bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); /* @} */ /** diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c index f73c43df..7a4c0b7e 100644 --- a/src/gqueue/gqueue.c +++ b/src/gqueue/gqueue.c @@ -75,7 +75,7 @@ bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue) { return pqueue->head == NULL; } - bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem) { gfxQueueASyncItem *pi; gfxSystemLock(); @@ -156,7 +156,7 @@ bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue) { return pqueue->head == NULL; } - bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem) { gfxQueueGSyncItem *pi; gfxSystemLock(); @@ -248,7 +248,7 @@ bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue) { return pqueue->head == NULL; } - bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { + bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem) { gfxQueueASyncItem *pi; gfxSystemLock(); From b0b35396395c3eadc5a656df995a17b266c4b374 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 14:54:25 +1000 Subject: [PATCH 18/18] Update GWIN list. Now supports item and page scrolling. A few bugs fixed. --- include/gwin/list.h | 3 +- src/gwin/list.c | 412 +++++++++++++++++++++++--------------------- 2 files changed, 213 insertions(+), 202 deletions(-) diff --git a/include/gwin/list.h b/include/gwin/list.h index d28206d9..99f5f532 100644 --- a/include/gwin/list.h +++ b/include/gwin/list.h @@ -52,6 +52,7 @@ typedef struct GListObject { #endif int cnt; // Number of items currently in the list (quicker than counting each time) + int top; // The element at the top of the visible list area gfxQueueASync list_head; // The list of items } GListObject; @@ -111,7 +112,7 @@ int gwinListAddItem(GHandle gh, const char* item, bool_t useAlloc); * * @api */ -char* gwinListItemGetText(GHandle gh, int item); +const char* gwinListItemGetText(GHandle gh, int item); /** * @brief Get the ID of an item with a given name diff --git a/src/gwin/list.c b/src/gwin/list.c index 2509260c..a938150f 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -23,11 +23,15 @@ #include // 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 SCROLLWIDTH 16 // the border from the scroll buttons to the frame #define ARROW 10 // arrow side length +#define TEXTGAP 1 // extra vertical padding for text -#define widget(gh) ((GListObject *)gh) +#define gh2obj ((GListObject *)gh) +#define gw2obj ((GListObject *)gw) +#define qi2li ((ListItem *)qi) +#define qix2li ((ListItem *)qix) +#define ple ((GEventGWinList *)pe) #define GLIST_FLG_MULTISELECT (GWIN_FIRST_CONTROL_FLAG << 0) #define GLIST_FLG_HASIMAGES (GWIN_FIRST_CONTROL_FLAG << 1) @@ -40,67 +44,13 @@ typedef struct ListItem { uint16_t param; // A parameter the user can specify himself const char* text; #if GWIN_LIST_IMAGES - gdispImage* pimg; + gdispImage* pimg; #endif } ListItem; -// select the next item in the list -static int _selectDown(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; - - break; - } - } - - _gwidgetRedraw((GHandle)gw); - - return ++i; - - #undef gcw -} - -// select the previous item in the list -static int _selectUp(GWidgetObject *gw) { - #define gcw ((GListObject *)gw) - - gfxQueueASyncItem *qi; - gfxQueueASyncItem *qi2; - uint16_t i; - - qi = gfxQueueASyncPeek(&gcw->list_head); - qi2 = qi; - - for (i = 0; qi2; qi2 = gfxQueueASyncNext(qi), i++) { - if (((ListItem*)qi2)->flags & GLIST_FLG_SELECTED) { - ((ListItem*)qi2)->flags &=~ GLIST_FLG_SELECTED; - ((ListItem*)qi)->flags |= GLIST_FLG_SELECTED; - - break; - } - - qi = qi2; - } - - _gwidgetRedraw((GHandle)gw); - - return --i; - - #undef gcw -} - static void sendListEvent(GWidgetObject *gw, int item) { GSourceListener* psl; GEvent* pe; - #define pse ((GEventGWinList *)pe) // Trigger a GWIN list event psl = 0; @@ -109,128 +59,188 @@ static void sendListEvent(GWidgetObject *gw, int item) { if (!(pe = geventGetEventBuffer(psl))) continue; - pse->type = GEVENT_GWIN_LIST; - pse->list = (GHandle)gw; - pse->item = item; + ple->type = GEVENT_GWIN_LIST; + ple->list = (GHandle)gw; + ple->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; + #if GDISP_NEED_CONVEX_POLYGON + static const point upArrow[] = { {0, ARROW}, {ARROW, ARROW}, {ARROW/2, 0} }; + static const point downArrow[] = { {0, 0}, {ARROW, 0}, {ARROW/2, ARROW} }; + #endif - fheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight); + const gfxQueueASyncItem* qi; + int i; + coord_t y, iheight, iwidth; + const GColorSet * ps; - // 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); + ps = (gw->g.flags & GWIN_FLG_ENABLED) ? &gw->pstyle->enabled : &gw->pstyle->disabled; + iheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + TEXTGAP; - // 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); + // the scroll area + if (gw2obj->cnt > (gw->g.height-2) / iheight) { + iwidth = gw->g.width - (SCROLLWIDTH+3); + gdispFillArea(gw->g.x+iwidth+2, gw->g.y+1, SCROLLWIDTH, gw->g.height-2, gdispBlendColor(ps->fill, gw->pstyle->background, 128)); + gdispDrawLine(gw->g.x+iwidth+1, gw->g.y+1, gw->g.x+iwidth+1, gw->g.y+gw->g.height-2, ps->edge); + #if GDISP_NEED_CONVEX_POLYGON + gdispFillConvexPoly(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), upArrow, 3, ps->fill); + gdispFillConvexPoly(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), downArrow, 3, ps->fill); + #else + #warning "GWIN: Lists display better when GDISP_NEED_CONVEX_POLGON is turned on" + gdispFillArea(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), ARROW, ARROW, ps->fill); + gdispFillArea(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), ARROW, ARROW, ps->fill); + #endif + } else + iwidth = gw->g.width - 2; - 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); + + // Find the top item + for (qi = gfxQueueASyncPeek(&gw2obj->list_head), i = 0; i < gw2obj->top && qi; qi = gfxQueueASyncNext(qi), i++); + + // Draw until we run out of room or items + for (y=1; y+iheight < gw->g.height-1 && qi; qi = gfxQueueASyncNext(qi), y += iheight) { + if (qi2li->flags & GLIST_FLG_SELECTED) { + //gdispFillStringBox(gw->g.x+1, gw->g.y+y, iwidth, iheight, qi2li->text, gwinGetDefaultFont(), gw->pstyle->background, ps->text, justifyLeft); + gdispFillStringBox(gw->g.x+1, gw->g.y+y, iwidth, iheight, qi2li->text, gwinGetDefaultFont(), ps->text, ps->fill, 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); + gdispFillStringBox(gw->g.x+1, gw->g.y+y, iwidth, iheight, qi2li->text, gwinGetDefaultFont(), ps->text, gw->pstyle->background, justifyLeft); } } - #undef gcw + // Fill any remaining item space + if (y < gw->g.height-1) + gdispFillArea(gw->g.x+1, gw->g.y+y, iwidth, gw->g.height-1-y, gw->pstyle->background); + + // the list frame + gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, ps->edge); } #if GINPUT_NEED_MOUSE - // a mouse down has occured over the list area + // a mouse down has occurred 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; + const gfxQueueASyncItem* qi; + int item, i, pgsz; + coord_t iheight; + (void) x; - uint16_t i, item_id, item_height; - const gfxQueueASyncItem* qi; + iheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + TEXTGAP; + pgsz = (gw->g.height-2)/iheight; + if (pgsz < 1) pgsz = 1; - item_id = -1; - - if (x > gw->g.width - BORDER_SCROLL) { - if (y < BORDER_SCROLL) - item_id = _selectUp(gw); - else if (y > gw->g.height - BORDER_SCROLL) - item_id = _selectDown(gw); - } else if (x < gw->g.width - BORDER_SCROLL - BORDER) { - item_height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + 2*BORDER; - item_id = (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; + // Handle click over the scroll bar + if (gw2obj->cnt > pgsz && x >= gw->g.width-(SCROLLWIDTH+2)) { + if (y < 2*ARROW) { + if (gw2obj->top > 0) { + gw2obj->top--; + _gwidgetRedraw(&gw->g); + } + } else if (y >= gw->g.height - 2*ARROW) { + if (gw2obj->top < gw2obj->cnt - pgsz) { + gw2obj->top++; + _gwidgetRedraw(&gw->g); + } + } else if (y < gw->g.height/2) { + if (gw2obj->top > 0) { + if (gw2obj->top > pgsz) + gw2obj->top -= pgsz; + else + gw2obj->top = 0; + _gwidgetRedraw(&gw->g); + } + } else { + if (gw2obj->top < gw2obj->cnt - pgsz) { + if (gw2obj->top < gw2obj->cnt - 2*pgsz) + gw2obj->top += pgsz; + else + gw2obj->top = gw2obj->cnt - pgsz; + _gwidgetRedraw(&gw->g); + } } + return; } - _gwidgetRedraw((GHandle)gw); + // Handle click over the list area + item = gw2obj->top + y / iheight; - // 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) + if (item < 0 || item >= gw2obj->cnt) return; - sendListEvent(gw, item_id); + for(qi = gfxQueueASyncPeek(&gw2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (item == i) + qi2li->flags |= GLIST_FLG_SELECTED; + else + qi2li->flags &=~ GLIST_FLG_SELECTED; + } - #undef gcw - #undef li + _gwidgetRedraw(&gw->g); + sendListEvent(gw, item); } #endif #if GINPUT_NEED_TOGGLE // a toggle-on has occurred static void ToggleOn(GWidgetObject *gw, uint16_t role) { - #define gcw ((GListObject *)gw) + const gfxQueueASyncItem * qi; + const gfxQueueASyncItem * qix; + int i; switch (role) { // select down case 0: - _selectDown(gw); + for (i = 0, qi = gfxQueueASyncPeek(&gw2obj->list_head); qi; qi = gfxQueueASyncNext(qi), i++) { + if ((qi2li->flags & GLIST_FLG_SELECTED)) { + qix = gfxQueueASyncNext(qi); + if (qix) { + qi2li->flags &=~ GLIST_FLG_SELECTED; + qix2li->flags |= GLIST_FLG_SELECTED; + _gwidgetRedraw(&gw->g); + } + break; + } + } break; // select up case 1: - _selectUp(gw); + qi = gfxQueueASyncPeek(&gw2obj->list_head); + qix = 0; + + for (i = 0; qi; qix = qi, qi = gfxQueueASyncNext(qi), i++) { + if ((qi2li->flags & GLIST_FLG_SELECTED)) + if (qix) { + qi2li->flags &=~ GLIST_FLG_SELECTED; + qix2li->flags |= GLIST_FLG_SELECTED; + _gwidgetRedraw(&gw->g); + } + break; + } + } break; } - - #undef gcw } static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) { if (role) - ((GListObject *)gw)->t_up = instance; + gw2obj->t_up = instance; else - ((GListObject *)gw)->t_dn = instance; + gw2obj->t_dn = instance; } static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) { - return role ? ((GListObject *)gw)->t_up : ((GListObject *)gw)->t_dn; + return role ? gw2obj->t_up : gw2obj->t_dn; } #endif static void _destroy(GHandle gh) { const gfxQueueASyncItem* qi; - while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) + while((qi = gfxQueueASyncGet(&gh2obj->list_head))) gfxFree((void *)qi); _gwidgetDestroy(gh); @@ -271,31 +281,32 @@ static const gwidgetVMT listVMT = { #endif }; -GHandle gwinListCreate(GListObject* widget, GWidgetInit* pInit) { - if (!(widget = (GListObject *)_gwidgetCreate(&widget->w, pInit, &listVMT))) +GHandle gwinListCreate(GListObject* gobj, GWidgetInit* pInit) { + if (!(gobj = (GListObject *)_gwidgetCreate(&gobj->w, pInit, &listVMT))) return 0; // initialize the item queue - gfxQueueASyncInit(&(widget->list_head)); - widget->cnt = 0; + gfxQueueASyncInit(&gobj->list_head); + gobj->cnt = 0; + gobj->top = 0; - gwinSetVisible(&widget->w.g, pInit->g.show); + gwinSetVisible(&gobj->w.g, pInit->g.show); - return (GHandle)widget; + return (GHandle)gobj; } 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) { + if (!(newItem = (ListItem *)gfxAlloc(sizeof(ListItem)+strlen(item_name)+1))) + return -1; + strcpy((char *)(newItem+1), item_name); item_name = (const char *)(newItem+1); + } else { + if (!(newItem = (ListItem *)gfxAlloc(sizeof(ListItem)))) + return -1; } // the item is not selected when added @@ -304,43 +315,43 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { newItem->text = item_name; // select the item if it's the first in the list - if (widget(gh)->cnt == 0) + if (gh2obj->cnt == 0) newItem->flags |= GLIST_FLG_SELECTED; // add the new item to the list - gfxQueueASyncPut(&widget(gh)->list_head, &newItem->q_item); + gfxQueueASyncPut(&gh2obj->list_head, &newItem->q_item); // increment the total amount of entries in the list widget - widget(gh)->cnt++; + gh2obj->cnt++; + + _gwidgetRedraw(gh); // return the position in the list (-1 because we start with index 0) - return widget(gh)->cnt-1; + return gh2obj->cnt-1; } -char* gwinListItemGetText(GHandle gh, int item) { - const gfxQueueASyncItem* qi; - uint16_t i; +const char* gwinListItemGetText(GHandle gh, int item) { + const gfxQueueASyncItem* qi; + int 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) + if (item < 0 || item >= gh2obj->cnt) return 0; - qi = gfxQueueASyncPeek(&widget(gh)->list_head); - - for (i = 0; i < item; i++) { - qi = gfxQueueASyncNext(qi); + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (i == item) + return qi2li->text; } - - return ((ListItem*)qi)->text; + return 0; } int gwinListFindText(GHandle gh, const char* text) { - const gfxQueueASyncItem* qi; - uint16_t i; + const gfxQueueASyncItem* qi; + int i; // is it a valid handle? if (gh->vmt != (gwinVMT *)&listVMT) @@ -350,9 +361,7 @@ int gwinListFindText(GHandle gh, const char* text) { if (!text) return -1; - qi = gfxQueueASyncPeek(&widget(gh)->list_head); - - for(qi = gfxQueueASyncPeek(&widget(gh)->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { if (strcmp(((ListItem *)qi)->text, text) == 0) return i; } @@ -361,15 +370,15 @@ int gwinListFindText(GHandle gh, const char* text) { } int gwinListGetSelected(GHandle gh) { - const gfxQueueASyncItem *qi; - int i; + 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) + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (qi2li->flags & GLIST_FLG_SELECTED) return i; } @@ -377,99 +386,100 @@ int gwinListGetSelected(GHandle gh) { } void gwinListItemSetParam(GHandle gh, int item, uint16_t param) { - const gfxQueueASyncItem* qi; - uint16_t i; + const gfxQueueASyncItem * qi; + int 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) + if (item < 0 || item > (gh2obj->cnt) - 1) return; - qi = gfxQueueASyncPeek(&widget(gh)->list_head); - - for (i = 0; i < item; i++) { - ((ListItem*)qi)->param = param; + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (i == item) { + qi2li->param = param; + break; + } } - - return; } void gwinListDeleteAll(GHandle gh) { - const gfxQueueASyncItem* qi; + gfxQueueASyncItem* qi; - while((qi = gfxQueueASyncGet(&((GListObject *)gh)->list_head))) - gfxFree((void *)qi); + // is it a valid handle? + if (gh->vmt != (gwinVMT *)&listVMT) + return; + + while((qi = gfxQueueASyncGet(&gh2obj->list_head))) + gfxFree(qi); + + gh2obj->cnt = 0; + gh2obj->top = 0; + _gwidgetRedraw(gh); } void gwinListItemDelete(GHandle gh, int item) { - const gfxQueueASyncItem* qi; - uint16_t i; + const gfxQueueASyncItem * qi; + int 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) + if (item < 0 || item >= gh2obj->cnt) return; - qi = gfxQueueASyncPeek(&widget(gh)->list_head); - - // get our item pointer - for (i = 0; i < item; i++) { - qi = gfxQueueASyncNext(qi); + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (i == item) { + gfxQueueASyncRemove(&gh2obj->list_head, (gfxQueueASyncItem*)qi); + gfxFree((void *)qi); + if (gh2obj->top >= item && gh2obj->top) + gh2obj->top--; + _gwidgetRedraw(gh); + break; + } } - - gfxQueueASyncRemove(&widget(gh)->list_head, qi); - gfxFree((void*)qi); } uint16_t gwinListItemGetParam(GHandle gh, int item) { - const gfxQueueASyncItem* qi; - uint16_t i; + const gfxQueueASyncItem * qi; + int 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) + if (item < 0 || item > (gh2obj->cnt) - 1) return 0; - qi = gfxQueueASyncPeek(&widget(gh)->list_head); - - for (i = 0; i < item; i++) { - qi = gfxQueueASyncNext(qi); + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (i == item) + return qi2li->param; } - - return ((ListItem*)qi)->param; + return 0; } bool_t gwinListItemIsSelected(GHandle gh, int item) { - const gfxQueueASyncItem* qi; - uint16_t i; + const gfxQueueASyncItem * qi; + int 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) + if (item < 0 || item > (gh2obj->cnt) - 1) return FALSE; - qi = gfxQueueASyncPeek(&widget(gh)->list_head); - - for (i = 0; i < item; i++) { - qi = gfxQueueASyncNext(qi); + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (i == item) + return (qi2li->flags & GLIST_FLG_SELECTED) ? TRUE : FALSE; } - - if (((ListItem*)qi)->flags & GLIST_FLG_SELECTED) - return TRUE; - else - return FALSE; + return FALSE; } int gwinListItemCount(GHandle gh) { @@ -477,7 +487,7 @@ int gwinListItemCount(GHandle gh) { if (gh->vmt != (gwinVMT *)&listVMT) return 0; - return widget(gh)->cnt; + return gh2obj->cnt; } #endif // GFX_USE_GWIN && GWIN_NEED_LIST