13 #include "../../gfx.h"
15 #if GFX_USE_GWIN && GWIN_NEED_LIST
17 #include "gwin_class.h"
22 #define LST_SCROLLWIDTH 16
23 #define LST_ARROW_SZ 10
24 #define LST_HORIZ_PAD 5
25 #define LST_VERT_PAD 2
28 #define gh2obj ((GListObject *)gh)
29 #define gw2obj ((GListObject *)gw)
30 #define qi2li ((ListItem *)qi)
31 #define qix2li ((ListItem *)qix)
32 #define ple ((GEventGWinList *)pe)
66 item = (gw2obj->top + y) / iheight;
68 if (item < 0 || item >= gw2obj->cnt)
71 for(qi = gfxQueueASyncPeek(&gw2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
74 qi2li->flags ^= GLIST_FLG_SELECTED;
79 qi2li->flags |= GLIST_FLG_SELECTED;
81 qi2li->flags &=~ GLIST_FLG_SELECTED;
86 sendListEvent(gw, item);
95 gw2obj->start_mouse_x = x;
96 gw2obj->start_mouse_y = y;
97 gw2obj->last_mouse_y = y;
100 if (gw->
g.
flags & GLIST_FLG_SCROLLSMOOTH)
108 if (x >= gw->
g.
width-(LST_SCROLLWIDTH+2) && (gw2obj->cnt > pgsz/iheight || (gw->
g.
flags & GLIST_FLG_SCROLLALWAYS))) {
109 if (y < 2*LST_ARROW_SZ) {
110 if (gw2obj->top > 0) {
111 gw2obj->top -= iheight;
116 }
else if (y >= gw->
g.
height - 2*LST_ARROW_SZ) {
117 if (gw2obj->top < gw2obj->cnt * iheight - pgsz) {
118 gw2obj->top += iheight;
119 if (gw2obj->top > gw2obj->cnt * iheight - pgsz)
120 gw2obj->top = gw2obj->cnt * iheight - pgsz;
123 }
else if (y < gw->g.height/2) {
124 if (gw2obj->top > 0) {
125 if (gw2obj->top > pgsz)
132 if (gw2obj->top < gw2obj->cnt * iheight - pgsz) {
133 if (gw2obj->top < gw2obj->cnt * iheight - 2*pgsz)
136 gw2obj->top = gw2obj->cnt * iheight - pgsz;
143 ListMouseSelect(gw, x, y);
148 if (!(gw->
g.
flags & GLIST_FLG_SCROLLSMOOTH))
152 if (abs(gw2obj->start_mouse_x - x) > 4 || abs(gw2obj->start_mouse_y - y) > 4)
155 ListMouseSelect(gw, x, y);
162 if (!(gw->
g.
flags & GLIST_FLG_SCROLLSMOOTH))
return;
164 if (gw2obj->last_mouse_y != y) {
165 oldtop = gw2obj->top;
168 gw2obj->top -= y - gw2obj->last_mouse_y;
169 if (gw2obj->top >= gw2obj->cnt * iheight - (gw->
g.
height-2))
170 gw2obj->top = gw2obj->cnt * iheight - (gw->
g.
height-2) - 1;
173 gw2obj->last_mouse_y = y;
174 if (oldtop != gw2obj->top)
180 #if GINPUT_NEED_TOGGLE
193 for (i = 0, qi = gfxQueueASyncPeek(&gw2obj->list_head); qi; qi = gfxQueueASyncNext(qi), i++) {
194 if ((qi2li->flags & GLIST_FLG_SELECTED)) {
195 qix = gfxQueueASyncNext(qi);
197 qi2li->flags &=~ GLIST_FLG_SELECTED;
198 qix2li->flags |= GLIST_FLG_SELECTED;
201 if (((i+2)*iheight - gw2obj->top) > gw->
g.
height){
202 gw2obj->top += iheight;
214 qi = gfxQueueASyncPeek(&gw2obj->list_head);
217 for (i = 0; qi; qix = qi, qi = gfxQueueASyncNext(qi), i++) {
218 if ((qi2li->flags & GLIST_FLG_SELECTED)) {
220 qi2li->flags &=~ GLIST_FLG_SELECTED;
221 qix2li->flags |= GLIST_FLG_SELECTED;
224 if (((i-1)*iheight) < gw2obj->top){
225 gw2obj->top -= iheight;
239 static void ListToggleAssign(
GWidgetObject *gw, gU16 role, gU16 instance) {
241 gw2obj->t_up = instance;
243 gw2obj->t_dn = instance;
247 return role ? gw2obj->t_up : gw2obj->t_dn;
251 static void ListDestroy(
GHandle gh) {
254 while((qi = gfxQueueASyncGet(&gh2obj->list_head)))
269 #if GINPUT_NEED_MOUSE
276 #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
281 #if GINPUT_NEED_TOGGLE
301 if (!(gobj = (GListObject *)_gwidgetCreate(g, &gobj->w, pInit, &listVMT)))
305 gfxQueueASyncInit(&gobj->list_head);
310 gobj->w.g.flags |= GLIST_FLG_SCROLLALWAYS;
311 gobj->w.g.flags |= GLIST_FLG_ENABLERENDER;
324 gh->
flags |= GLIST_FLG_ENABLERENDER;
327 gh->
flags &=~ GLIST_FLG_ENABLERENDER;
336 ((GListObject*)gh)->w.g.flags &=~(GLIST_FLG_SCROLLSMOOTH | GLIST_FLG_SCROLLALWAYS);
339 ((GListObject*)gh)->w.g.flags |= GLIST_FLG_SCROLLALWAYS;
346 ((GListObject*)gh)->w.g.flags |= GLIST_FLG_SCROLLSMOOTH;
359 gMemSize len = strlen(text)+1;
363 memcpy((
char *)(newItem+1), text, len);
364 text = (
const char *)(newItem+1);
373 newItem->text = text;
374 #if GWIN_NEED_LIST_IMAGES
380 newItem->flags |= GLIST_FLG_SELECTED;
383 gfxQueueASyncPut(&gh2obj->list_head, &newItem->q_item);
391 return gh2obj->cnt-1;
404 if (item < 0 || item > (gh2obj->cnt) - 1)
407 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
412 gMemSize len = strlen(text)+1;
416 memcpy((
char *)(newItem+1), text, len);
417 text = (
const char *)(newItem+1);
424 newItem->flags = qi2li->flags;
425 newItem->param = qi2li->param;
426 newItem->text = text;
427 #if GWIN_NEED_LIST_IMAGES
428 newItem->pimg = qi2li->pimg;
432 gfxQueueASyncInsert(&gh2obj->list_head, &newItem->q_item, &qi2li->q_item);
433 gfxQueueASyncRemove(&gh2obj->list_head, &qi2li->q_item);
451 if (item < 0 || item >= gh2obj->cnt)
454 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
473 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
474 if (strcmp(((
ListItem *)qi)->text, text) == 0)
493 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
494 if (qi2li->flags & GLIST_FLG_SELECTED)
510 if (item < 0 || item > (gh2obj->cnt) - 1)
513 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
515 qi2li->param = param;
528 while((qi = gfxQueueASyncGet(&gh2obj->list_head)))
531 gh->
flags &= ~GLIST_FLG_HASIMAGES;
546 if (item < 0 || item >= gh2obj->cnt)
549 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
554 if (gh2obj->top >= item && gh2obj->top)
571 if (item < 0 || item > (gh2obj->cnt) - 1)
574 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
590 if (item < 0 || item > (gh2obj->cnt) - 1)
593 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
595 return (qi2li->flags & GLIST_FLG_SELECTED) ? gTrue : gFalse;
629 if (item < 0 || item >= gh2obj->cnt)
634 for(qi = gfxQueueASyncPeek(&gh2obj->list_head); qi; qi = gfxQueueASyncNext(qi)) {
635 if (qi2li->flags & GLIST_FLG_SELECTED) {
636 qi2li->flags &= ~GLIST_FLG_SELECTED;
643 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
646 qi2li->flags |= GLIST_FLG_SELECTED;
648 qi2li->flags &= ~GLIST_FLG_SELECTED;
663 if (item < 0 || item >= gh2obj->cnt)
668 gh2obj->top = iheight * item;
671 if (gh2obj->top > gh2obj->cnt * iheight - gh->
height-2)
672 gh2obj->top = gh2obj->cnt * iheight - gh->
height-2;
679 #if GWIN_NEED_LIST_IMAGES
689 if (item < 0 || item > (gh2obj->cnt) - 1)
692 for(qi = gfxQueueASyncPeek(&gh2obj->list_head), i = 0; qi; qi = gfxQueueASyncNext(qi), i++) {
696 gh->
flags |= GLIST_FLG_HASIMAGES;
706 gCoord x, y, iheight, iwidth;
709 #if GWIN_NEED_LIST_IMAGES
712 #if GDISP_NEED_CONVEX_POLYGON
713 static const gPoint upArrow[] = { {0, LST_ARROW_SZ}, {LST_ARROW_SZ, LST_ARROW_SZ}, {LST_ARROW_SZ/2, 0} };
714 static const gPoint downArrow[] = { {0, 0}, {LST_ARROW_SZ, 0}, {LST_ARROW_SZ/2, LST_ARROW_SZ} };
724 if (!(gw->
g.
flags & GLIST_FLG_ENABLERENDER))
732 if (gw->
g.
flags & GLIST_FLG_SCROLLSMOOTH) {
733 iwidth = gw->
g.
width - 2 - 4;
734 if (gw2obj->cnt > 0) {
735 int max_scroll_value = gw2obj->cnt * iheight - gw->
g.
height-2;
736 if (max_scroll_value > 0) {
737 int bar_height = (gw->
g.
height-2) * (gw->
g.
height-2) / (gw2obj->cnt * iheight);
742 }
else if ((gw2obj->cnt > (gw->
g.
height-2) / iheight) || (gw->
g.
flags & GLIST_FLG_SCROLLALWAYS)) {
743 iwidth = gw->
g.
width - (LST_SCROLLWIDTH+3);
746 #if GDISP_NEED_CONVEX_POLYGON
750 #if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
751 #warning "GWIN: Lists display better when GDISP_NEED_CONVEX_POLYGON is turned on"
752 #elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
753 COMPILER_WARNING(
"GWIN: Lists display better when GDISP_NEED_CONVEX_POLYGON is turned on")
755 gdispGFillArea(gw->
g.
display, gw->
g.
x+iwidth+((LST_SCROLLWIDTH-LST_ARROW_SZ)/2+2), gw->
g.
y+(LST_ARROW_SZ/2+1), LST_ARROW_SZ, LST_ARROW_SZ, ps->
fill);
761 #if GWIN_NEED_LIST_IMAGES
762 if ((gw->
g.
flags & GLIST_FLG_HASIMAGES)) {
770 for (qi = gfxQueueASyncPeek(&gw2obj->list_head), i = iheight - 1; i < gw2obj->top && qi; qi = gfxQueueASyncNext(qi), i+=iheight);
781 for (y = 1-(gw2obj->top%iheight); y < gw->g.height-2 && qi; qi = gfxQueueASyncNext(qi), y += iheight) {
784 #if GWIN_NEED_LIST_IMAGES
785 if ((gw->
g.
flags & GLIST_FLG_HASIMAGES)) {
789 sy = (qi2li->flags & GLIST_FLG_SELECTED) ? 0 : (iheight-LST_VERT_PAD);
790 if (!(gw->
g.
flags & GWIN_FLG_SYSENABLED))
791 sy += 2*(iheight-LST_VERT_PAD);
792 while (sy > qi2li->pimg->height)
793 sy -= iheight-LST_VERT_PAD;
804 if (y < gw->g.height-1)
COLOR_TYPE gColor
The color type definition.
gColor gdispBlendColor(gColor fg, gColor bg, gU8 alpha)
Blend 2 colors according to the alpha.
gCoord gdispGetFontMetric(gFont font, gFontmetric metric)
Get a metric of a font.
void gdispGSetClip(GDisplay *g, gCoord x, gCoord y, gCoord cx, gCoord cy)
Clip all drawing to the defined area.
void gdispGFillArea(GDisplay *g, gCoord x, gCoord y, gCoord cx, gCoord cy, gColor color)
Fill an area with a color.
void gdispGDrawLine(GDisplay *g, gCoord x0, gCoord y0, gCoord x1, gCoord y1, gColor color)
Draw a line.
void gdispGFillStringBox(GDisplay *g, gCoord x, gCoord y, gCoord cx, gCoord cy, const char *str, gFont font, gColor color, gColor bgColor, gJustify justify)
Draw a text string vertically centered within the specified box. The box background is filled with th...
gI16 gCoord
The type for a coordinate or length on the screen.
void gdispGFillConvexPoly(GDisplay *g, gCoord tx, gCoord ty, const gPoint *pntarray, unsigned cnt, gColor color)
Fill a convex polygon.
void gdispGDrawBox(GDisplay *g, gCoord x, gCoord y, gCoord cx, gCoord cy, gColor color)
Draw a rectangular box.
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener's event buffer has been filled.
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
void * gfxAlloc(gMemSize sz)
Allocate memory.
void gfxFree(void *ptr)
Free memory.
gdispImageError gdispGImageDraw(GDisplay *g, gImage *img, gCoord x, gCoord y, gCoord cx, gCoord cy, gCoord sx, gCoord sy)
Draw the image.
gBool gdispImageIsOpen(gImage *img)
Is an image open.
void gdispImageSetBgColor(gImage *img, gColor bgcolor)
Set the background color of the image.
const char * gwinListItemGetText(GHandle gh, int item)
Get the name behind an item with a given ID.
gU16 gwinListItemGetParam(GHandle gh, int item)
Get the custom parameter of an item with a given ID.
int gwinListGetSelected(GHandle gh)
Get the ID of the selected item.
void gwinListItemSetParam(GHandle gh, int item, gU16 param)
Set the custom parameter of an item with a given ID.
const char * gwinListGetSelectedText(GHandle gh)
Get the text of the selected item.
scroll_t
Enum to change the behaviour of the scroll bar.
void gwinListItemSetText(GHandle gh, int item, const char *text, gBool useAlloc)
Set the custom parameter of an item with a given ID.
void gwinListViewItem(GHandle gh, int item)
Scroll the list so the specified item is in view.
void gwinListSetSelected(GHandle gh, int item, gBool doSelect)
Set whether a specific item is selected or not.
int gwinListFindText(GHandle gh, const char *text)
Get the ID of an item with a given name.
gBool gwinListItemIsSelected(GHandle gh, int item)
Check if an item with a given ID is selected.
#define GLIST_FLG_MULTISELECT
The internal list object flags.
int gwinListAddItem(GHandle gh, const char *text, gBool useAlloc)
Add an item to the list.
GHandle gwinGListCreate(GDisplay *g, GListObject *widget, GWidgetInit *pInit, gBool multiselect)
Create a list widget.
void gwinListDeleteAll(GHandle gh)
Delete all the items of the list.
void gwinListItemSetImage(GHandle gh, int item, gImage *pimg)
Set the image for a list item.
int gwinListItemCount(GHandle gh)
Get the amount of items within the list.
void gwinListSetScroll(GHandle gh, scroll_t flag)
Change the behaviour of the scroll bar.
void gwinListItemDelete(GHandle gh, int item)
Delete an item from the list.
void gwinListEnableRender(GHandle gh, gBool ena)
Enable or disable the rendering of the list.
#define GEVENT_GWIN_LIST
The event type for a list event.
void gwinListDefaultDraw(GWidgetObject *gw, void *param)
The default rendering function for the list widget.
void gwinRedraw(GHandle gh)
Redraw a window.
void gwinSetVisible(GHandle gh, gBool visible)
Sets whether a window is visible or not.
A window object structure.
const struct gwinVMT * vmt
The internal list item structure.
The structure for an image.
Type for a 2D point on the screen.
The Virtual Method Table for a GWIN window.