From 312e759124098da0d6e2223698d39cb21bf9d5ae Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 15:58:46 +1000 Subject: Add GWIN List multi-select support --- src/gwin/list.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gwin/list.c b/src/gwin/list.c index a938150f..f3f154a9 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -172,10 +172,17 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { return; 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; + if ((gw->g.flags & GLIST_FLG_MULTISELECT)) { + if (item == i) { + qi2li->flags ^= GLIST_FLG_SELECTED; + break; + } + } else { + if (item == i) + qi2li->flags |= GLIST_FLG_SELECTED; + else + qi2li->flags &=~ GLIST_FLG_SELECTED; + } } _gwidgetRedraw(&gw->g); @@ -281,7 +288,7 @@ static const gwidgetVMT listVMT = { #endif }; -GHandle gwinListCreate(GListObject* gobj, GWidgetInit* pInit) { +GHandle gwinListCreate(GListObject* gobj, GWidgetInit* pInit, bool_t multiselect) { if (!(gobj = (GListObject *)_gwidgetCreate(&gobj->w, pInit, &listVMT))) return 0; @@ -289,6 +296,8 @@ GHandle gwinListCreate(GListObject* gobj, GWidgetInit* pInit) { gfxQueueASyncInit(&gobj->list_head); gobj->cnt = 0; gobj->top = 0; + if (multiselect) + gobj->w.g.flags |= GLIST_FLG_MULTISELECT; gwinSetVisible(&gobj->w.g, pInit->g.show); @@ -315,7 +324,7 @@ 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 (gh2obj->cnt == 0) + if (gh2obj->cnt == 0 && !(gh->flags & GLIST_FLG_MULTISELECT)) newItem->flags |= GLIST_FLG_SELECTED; // add the new item to the list @@ -377,6 +386,10 @@ int gwinListGetSelected(GHandle gh) { if (gh->vmt != (gwinVMT *)&listVMT) return -1; + // Multi-select always returns -1. Use gwinListItemIsSelected() instead + if ((gh->flags & GLIST_FLG_MULTISELECT)) + return -1; + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { if (qi2li->flags & GLIST_FLG_SELECTED) return i; -- cgit v1.2.3 From 2e91479bd576160b475cc63d1f43cc119d90e187 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 1 Aug 2013 18:05:48 +1000 Subject: Add image support to GWIN Listboxes. Updated GWIN widgets demo to match. --- src/gwin/list.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gwin/list.c b/src/gwin/list.c index f3f154a9..cf567a81 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -27,15 +27,19 @@ #define ARROW 10 // arrow side length #define TEXTGAP 1 // extra vertical padding for text +// Macro's to assist in data type conversions #define gh2obj ((GListObject *)gh) #define gw2obj ((GListObject *)gw) #define qi2li ((ListItem *)qi) #define qix2li ((ListItem *)qix) #define ple ((GEventGWinList *)pe) +// Flags for the GListObject #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) + +// Flags on a ListItem. +#define GLIST_FLG_SELECTED 0x0001 typedef struct ListItem { gfxQueueASyncItem q_item; // This must be the first member in the struct @@ -43,7 +47,7 @@ typedef struct ListItem { uint16_t flags; uint16_t param; // A parameter the user can specify himself const char* text; - #if GWIN_LIST_IMAGES + #if GWIN_NEED_LIST_IMAGES gdispImage* pimg; #endif } ListItem; @@ -77,11 +81,16 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { const gfxQueueASyncItem* qi; int i; - coord_t y, iheight, iwidth; + coord_t x, y, iheight, iwidth; + color_t fill; const GColorSet * ps; + #if GWIN_NEED_LIST_IMAGES + coord_t sy; + #endif ps = (gw->g.flags & GWIN_FLG_ENABLED) ? &gw->pstyle->enabled : &gw->pstyle->disabled; iheight = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight) + TEXTGAP; + x = 1; // the scroll area if (gw2obj->cnt > (gw->g.height-2) / iheight) { @@ -99,18 +108,38 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) { } else iwidth = gw->g.width - 2; + #if GWIN_NEED_LIST_IMAGES + if ((gw->g.flags & GLIST_FLG_HASIMAGES)) { + x += iheight; + iwidth -= iheight; + } + #endif + // 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+1, gw->g.y+y, iwidth, iheight, qi2li->text, gwinGetDefaultFont(), ps->text, gw->pstyle->background, justifyLeft); - } + fill = (qi2li->flags & GLIST_FLG_SELECTED) ? ps->fill : gw->pstyle->background; + #if GWIN_NEED_LIST_IMAGES + if ((gw->g.flags & GLIST_FLG_HASIMAGES)) { + // Clear the image area + gdispFillArea(gw->g.x+1, gw->g.y+y, x-1, iheight, fill); + if (qi2li->pimg && gdispImageIsOpen(qi2li->pimg)) { + // Calculate which image + sy = (qi2li->flags & GLIST_FLG_SELECTED) ? 0 : (iheight-TEXTGAP); + if (!(gw->g.flags & GWIN_FLG_ENABLED)) + sy += 2*(iheight-TEXTGAP); + while (sy > qi2li->pimg->height) + sy -= iheight-TEXTGAP; + // Draw the image + gdispImageSetBgColor(qi2li->pimg, fill); + gdispImageDraw(qi2li->pimg, gw->g.x+1, gw->g.y+y, iheight-TEXTGAP, iheight-TEXTGAP, 0, sy); + } + } + #endif + gdispFillStringBox(gw->g.x+x, gw->g.y+y, iwidth, iheight, qi2li->text, gwinGetDefaultFont(), ps->text, fill, justifyLeft); } // Fill any remaining item space @@ -322,6 +351,9 @@ int gwinListAddItem(GHandle gh, const char* item_name, bool_t useAlloc) { newItem->flags = 0; newItem->param = 0; newItem->text = item_name; + #if GWIN_NEED_LIST_IMAGES + newItem->pimg = 0; + #endif // select the item if it's the first in the list if (gh2obj->cnt == 0 && !(gh->flags & GLIST_FLG_MULTISELECT)) @@ -428,6 +460,7 @@ void gwinListDeleteAll(GHandle gh) { while((qi = gfxQueueASyncGet(&gh2obj->list_head))) gfxFree(qi); + gh->flags &= ~GLIST_FLG_HASIMAGES; gh2obj->cnt = 0; gh2obj->top = 0; _gwidgetRedraw(gh); @@ -503,6 +536,30 @@ int gwinListItemCount(GHandle gh) { return gh2obj->cnt; } +#if GWIN_NEED_LIST_IMAGES + void gwinListItemSetImage(GHandle gh, int item, gdispImage *pimg) { + 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 > (gh2obj->cnt) - 1) + return; + + for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) { + if (i == item) { + qi2li->pimg = pimg; + if (pimg) + gh->flags |= GLIST_FLG_HASIMAGES; + break; + } + } + } +#endif + #endif // GFX_USE_GWIN && GWIN_NEED_LIST /** @} */ -- cgit v1.2.3