/* dropdown.c * * by Revin Guillen * * Implements a drop-down list box * * Allegro GUI Clinic Example * http://students.washington.edu/revin/gui/ */ #include int d_drop_down_proc(int msg, DIALOG *d, int c); char *list_items[] = { "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth", NULL }; DIALOG main_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ { d_clear_proc, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, NULL }, { d_drop_down_proc, 280, 110, 80, 20, 15, 0, 0, 0, 0, 0, list_items }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } }; /* d_drop_down_proc * * A drop-down list box. The dp parameter should point * to an array of strings to use for the list items. The * array is terminated by a NULL entry. d1 holds the * current selection. d2 is reserved. */ int d_drop_down_proc(int msg, DIALOG *d, int c) { int num_items = 0; char **items = d->dp; int fgcol, bgcol; int old_x=-1, old_y=-1; int mx, my; int bot; int text_y, ry; int ht; int i; /* get the number of items */ if (items != NULL) { while (items[num_items++] != NULL) ; } num_items--; /* clamp the value of the selection index */ if (d->d1 >= num_items) d->d1 = num_items - 1; ht = text_height(font) + 4; bot = d->y + d->h + (ht*num_items); fgcol = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; bgcol = d->bg; switch (msg) { case MSG_DRAW: if ( !(d->flags & D_HIDDEN) ) { rect(screen, d->x, d->y, d->x+d->w, d->y+d->h, fgcol); /* invert the colors */ if (d->flags & D_GOTFOCUS) { i = fgcol; fgcol = bgcol; bgcol = i; } rectfill(screen, d->x+1, d->y+1, d->x+d->w-1, d->y+d->h-1, bgcol); text_mode(-1); text_y = d->y+(d->h/2)-(text_height(font)/2)+1; gui_textout(screen, items[d->d1], d->x+6, text_y, fgcol, 0); /* if we've got the focus */ if (d->flags & D_GOTFOCUS) { for (i=d->x+2; ix+d->w; i+=2) { putpixel(screen, i, d->y+2, fgcol); putpixel(screen, i, d->y+d->h-2, fgcol); } for (i=d->y+2; iy+d->h; i+=2) { putpixel(screen, d->x+2, i, fgcol); putpixel(screen, d->x+d->w-2, i, fgcol); } } /* restore the colors */ if (d->flags & D_GOTFOCUS) { i = fgcol; fgcol = bgcol; bgcol = i; } /* if we're dropped down */ if (d->flags & D_SELECTED) { rect(screen, d->x, d->y+d->h, d->x+d->w, bot, fgcol); rectfill(screen, d->x+1, d->y+d->h+1, d->x+d->w-1, bot-1, bgcol); for (i=0; iy+d->h+(i*ht)+3; if (i == d->d2) { ry = d->y+d->h+(i*ht); rectfill(screen, d->x+1, ry, d->x+d->w-1, ry+ht, fgcol); gui_textout(screen, items[i], d->x+4, text_y, bgcol, 0); } else { gui_textout(screen, items[i], d->x+4, text_y, fgcol, 0); } } } } break; case MSG_CLICK: if ( !(d->flags & D_HIDDEN) && !(d->flags & D_DISABLED) ) { d->d2 = -10000; /* below lowest possible */ /* only works with the left mouse button */ while (gui_mouse_b() & 0x01) { mx = gui_mouse_x(); my = gui_mouse_y(); if (((mx != old_x) || (my != old_y)) && ((mx > d->x) && (mx < d->x+d->w) && (my > d->y) && (my < bot ))) { old_x = mx; old_y = my; if (d->d2 != ((my-d->y-d->h)/ht)) { if (d->flags & D_SELECTED) { if (my >= d->y+d->h) { d->d2 = ((my-d->y-d->h)/ht); } } else { d->d2 = d->d1; } /* signals a dropped-down state */ d->flags |= D_SELECTED; scare_mouse(); /* redraw in the dropped-down position */ SEND_MESSAGE(d, MSG_DRAW, 0); unscare_mouse(); } } } /* return to non-dropped-down state */ d->flags &= ~D_SELECTED; /* finalize the selection */ if ((mx > d->x) && (mx < d->x+d->w) && (my > d->y) && (my < bot )) d->d1 = d->d2; return D_REDRAW; } break; case MSG_CHAR: if ( !(d->flags & D_HIDDEN) && !(d->flags & D_DISABLED)) { i=FALSE; if ((c >> 8) == KEY_UP) { if (d->d1 > 0) d->d1--; i=TRUE; } else if ((c >> 8) == KEY_DOWN) { if (d->d1 < num_items) d->d1++; i=TRUE; } else if ((c >> 8) == KEY_HOME) { d->d1 = 0; i=TRUE; } else if ((c >> 8) == KEY_END) { d->d1 = num_items; i=TRUE; } d->d2 = d->d1; scare_mouse(); SEND_MESSAGE(d, MSG_DRAW, 0); unscare_mouse(); if (i) return D_USED_CHAR; } break; case MSG_WANTFOCUS: return D_WANTFOCUS; } return D_O_K; } int main() { /* initialize */ allegro_init(); install_keyboard(); install_mouse(); install_timer(); set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0); set_palette(desktop_palette); /* run the dialog */ do_dialog(main_dialog, -1); return 0; }