You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bomberclone/src/menulists.c

311 lines
9.9 KiB

/* $Id: menulists.c,v 1.2 2003/12/26 02:20:10 stpohle Exp $
* Menuhandling: lists */
#include "basic.h"
#include "bomberclone.h"
#include "menu.h"
#include "menugui.h"
/* create a entryimages only in the menudatas.. darf all this only when menu_loop
* is called */
void menu_create_list (char *name, int x, int y, int w, int h, _charlist *data, _charlist **selected, int id) {
int i = menu_getlastitem(menu.items);
if (i == -1) { /* first entry in the itemslist */
menu.items = &menuitems[0];
i = 0;
}
else if (i >= MENU_MAXENTRYS) { /* max items reached, ignore new item */
d_fatal ("menu_create_entry: MENU_MAXENTRYS reached. Item Ignored\n");
return;
}
else { /* add new item to the list */
menuitems[i].next = &menuitems[i+1];
i++;
}
menuitems[i].type = MENU_list;
menuitems[i].pos.w = (1 + (int)
((w - menu.listimages[0][0]->w - menu.listimages[0][2]->w) / menu.listimages[0][1]->w))
* menu.listimages[0][1]->w + menu.listimages[0][0]->w + menu.listimages[0][2]->w;
menuitems[i].pos.h = (1 + (int)
((h - menu.listimages[0][0]->h - menu.listimages[0][6]->h) / menu.listimages[0][3]->h))
* menu.listimages[0][3]->h + menu.listimages[0][0]->h + menu.listimages[0][6]->h;
if (x != -1)
menuitems[i].pos.x = x;
else
menuitems[i].pos.x = (menu.oldscreenpos.w - 2 * menu.images[0]->w - menuitems[i].pos.w) / 2;
menuitems[i].pos.y = y;
menuitems[i].ptrdata = (char *) selected;
menuitems[i].list = data;
menuitems[i].id = id;
strncpy (menuitems[i].label, name, MENU_TITLELEN);
};
/* draw only a part of the background */
void menu_draw_listbackground (_menuitem *mi, SDL_Rect *updaterect) {
int x,y, dx, dy;
SDL_Rect dest, cdest, src, csrc, window;
y = 0; // start at the updaterect. start pos
for (; y <= (mi->pos.h - 2*menu.listimages[0][0]->h - 1)/menu.listimages[0][4]->h; y++) {
x = 0; // start at the updaterect. start pos
for (; x <= (mi->pos.w - 2*menu.listimages[0][0]->w - 1)/menu.listimages[0][4]->w; x++) {
dest.x = x * menu.listimages[0][4]->w; // start pos
dest.y = y * menu.listimages[0][4]->h;
dx = (1+x) * menu.listimages[0][4]->w; // end pos
if (dx >= (mi->pos.w - 2*menu.listimages[0][0]->w))
dest.w = menu.listimages[0][4]->w - (dx - (mi->pos.w - 2*menu.listimages[0][0]->w));
else
dest.w = menu.listimages[0][4]->w;
dy = (1+y) * menu.listimages[0][4]->h;
if (dy >= (mi->pos.h - 2*menu.listimages[0][0]->h))
dest.h = menu.listimages[0][4]->h - (dy - (mi->pos.h - 2*menu.listimages[0][0]->h));
else
dest.h = menu.listimages[0][4]->h;
if (dest.w > 0 || dest.h > 0) {
dest.x += MENUOFFSET_X + mi->pos.x + menu.listimages[0][0]->w;
dest.y += MENUOFFSET_Y + mi->pos.y + menu.listimages[0][0]->h;
src.x = 0; src.y = 0; src.h = dest.h; src.w = dest.w;
if (updaterect == NULL)
gfx_blit (menu.listimages[0][4], &src, gfx.screen, &dest, 10000);
else {
window = *updaterect;
window.x += MENUOFFSET_X + mi->pos.x + menu.listimages[0][0]->w;
window.y += MENUOFFSET_Y + mi->pos.y + menu.listimages[0][0]->h;
rect_clipping (&src, &dest, &window, &csrc, &cdest);
if (csrc.w < UINT16_HALF && csrc.h < UINT16_HALF && cdest.w < UINT16_HALF && cdest.h < UINT16_HALF)
gfx_blit (menu.listimages[1][4], &csrc, gfx.screen, &cdest, 10000);
}
}
}
}
};
/* gets the number of the selected item
* returns the elemennumber or -1 if none where selected */
int menu_list_getselected (_menuitem *mi) {
int res = -1, i;
_charlist *l;
if (mi == NULL || mi->ptrdata == NULL) return -1;
for (i = 0, l = mi->list; l != NULL && res == -1; l = l->next, i++)
if (l == *((_charlist **)mi->ptrdata))
res = i;
return res;
};
/* gets the number of elements */
int menu_list_getcount (_menuitem *mi) {
int count = 0;
_charlist *l;
for (l = mi->list; l != NULL; l = l->next, count++);
return count;
};
/* select the element, return 0 if it was not working else 1 */
int menu_list_select (_menuitem *mi, int element) {
_charlist *l = mi->list;
int i = element;
/* set the new element if there is any */
for (; i > 0 && l != NULL; l = l->next, i--);
// check element
if (l == NULL || i < 0)
return 0;
*(_charlist **)mi->ptrdata = l;
menu_draw_list (mi);
return 1;
};
/* select the previous element in the list */
void menu_list_select_prev (_menuitem *mi) {
int sel = menu_list_getselected(mi);
if (!menu_list_select (mi, sel - 1))
menu_list_select (mi, menu_list_getcount(mi) - 1);
};
/* select the next element in the list */
void menu_list_select_next (_menuitem *mi) {
int sel = menu_list_getselected (mi);
if (!menu_list_select (mi, sel + 1))
menu_list_select (mi, 0);
};
/* this part will draw the textelement in a list */
void menu_draw_listtext (_menuitem *mi) {
int count = menu_list_getcount (mi);
int selected = menu_list_getselected (mi);
int countvis = (mi->pos.h - menu.listimages[0][0]->h - menu.listimages[0][6]->h)
/ font[MENU_BUTTON_FONTSIZE].size.y; // number of visible elements
_charlist *list;
int maxx, // max chars in X
dy, // current y position
dx, // x position, to start drawing
start;// start with this element
SDL_Rect wnd; // needed for the selected field to redraw the background
char text[255];
/* start element */
if (selected == -1)
start = 0;
else {
if ((start = selected - countvis/2) < 0)
start = 0;
else if ((start + countvis > count) && (count - countvis >= 0))
start = count - countvis;
}
list = &mi->list[start];
/* calculate the max numbers of chars to draw */
maxx = (mi->pos.w - menu.listimages[0][0]->w - menu.listimages[0][2]->w) / font[MENU_BUTTON_FONTSIZE].size.x;
/* calculate start point (y) */
dy = MENUOFFSET_Y + mi->pos.y + ((mi->pos.h - countvis*font[MENU_BUTTON_FONTSIZE].size.y) / 2);
/* draw the elements */
for (;countvis > 0 && list != NULL; countvis--, list = list->next) {
/* calculate dx and print only the text which fixs in the list */
strncpy (text, list->text, maxx);
dx = MENUOFFSET_X + mi->pos.x + ((mi->pos.w - strlen (text)*font[MENU_BUTTON_FONTSIZE].size.x) / 2);
if (mi->ptrdata != NULL && list == *(_charlist **)mi->ptrdata) {
// this is the selected element
wnd.x = menu.listimages[0][0]->w;
wnd.y = dy - (MENUOFFSET_Y + mi->pos.y + menu.listimages[0][0]->h);
wnd.w = mi->pos.w - menu.listimages[0][0]->w - menu.listimages[0][2]->w;
wnd.h = font[MENU_BUTTON_FONTSIZE].size.y;
menu_draw_listbackground (mi, &wnd);
font_gfxdraw (dx, dy, text, MENU_BUTTON_FONTSIZE, COLOR_black, 10000);
}
else
font_gfxdraw (dx, dy, text, MENU_BUTTON_FONTSIZE, COLOR_yellow, 10000);
dy += font[MENU_BUTTON_FONTSIZE].size.y;
}
};
/* draw the menuitem button or bool
* menuitem->pos.[x|y|w] - Position and X-Size inside the menu
* label - Text of the Button/Bool
*/
void menu_draw_list (_menuitem *mi) {
int i, focus;
SDL_Rect dest;
if (mi->type != MENU_list)
return;
dest.x = mi->pos.x;
dest.y = mi->pos.y;
dest.w = mi->pos.w;
dest.h = menu.listimages[0][0]->h;
menu_draw_background (&dest);
/* check the focus of the button */
if (menu.focusvis && mi == menu.focus)
focus = 1;
else
focus = 0;
// draw the top left and right of the list
dest.x = MENUOFFSET_X + mi->pos.x;
dest.y = MENUOFFSET_Y + mi->pos.y;
dest.w = menu.listimages[focus][0]->w;
dest.h = menu.listimages[focus][0]->h;
gfx_blit (menu.listimages[focus][0], NULL, gfx.screen, &dest, 10000);
dest.x = MENUOFFSET_X + mi->pos.x + mi->pos.w - menu.listimages[focus][2]->w;
gfx_blit (menu.listimages[focus][2], NULL, gfx.screen, &dest, 10000);
// draw the bottom left and right of the list
dest.y = MENUOFFSET_Y + mi->pos.y + mi->pos.h - menu.listimages[focus][8]->h;
gfx_blit (menu.listimages[focus][8], NULL, gfx.screen, &dest, 10000);
dest.x = MENUOFFSET_X + mi->pos.x;
gfx_blit (menu.listimages[focus][6], NULL, gfx.screen, &dest, 10000);
// draw the top and blow center of the list
for (i = 0; i < ((mi->pos.w -
(menu.listimages[focus][0]->w + menu.listimages[focus][2]->w))
/ menu.listimages[focus][1]->w); i++) {
dest.x = MENUOFFSET_X + mi->pos.x + menu.listimages[focus][0]->w + (i * menu.listimages[focus][1]->w);
dest.y = MENUOFFSET_Y + mi->pos.y;
dest.w = menu.listimages[focus][1]->w;
dest.h = menu.listimages[focus][1]->h;
gfx_blit (menu.listimages[focus][1], NULL, gfx.screen, &dest, 10000);
dest.y = MENUOFFSET_Y + mi->pos.y + mi->pos.h - menu.listimages[focus][7]->h;
gfx_blit (menu.listimages[focus][7], NULL, gfx.screen, &dest, 10000);
}
// draw the left and the right side of the list
for (i = 0; i < ((mi->pos.h -
(menu.listimages[focus][0]->h + menu.listimages[focus][6]->h))
/ menu.listimages[focus][3]->h); i++) {
dest.x = MENUOFFSET_X + mi->pos.x;
dest.y = MENUOFFSET_Y + mi->pos.y + menu.listimages[focus][0]->h + (i * menu.listimages[focus][3]->h);
dest.w = menu.listimages[focus][3]->w;
dest.h = menu.listimages[focus][3]->h;
gfx_blit (menu.listimages[focus][3], NULL, gfx.screen, &dest, 10000);
dest.x = MENUOFFSET_X + mi->pos.x + mi->pos.w - menu.listimages[focus][5]->w;
gfx_blit (menu.listimages[focus][5], NULL, gfx.screen, &dest, 10000);
}
menu_draw_listbackground (mi, NULL);
menu_draw_listtext (mi);
};
/* handle the event on the button
* on ESC - Reload Old Data
* on lose focus - Save Data
*/
int menu_event_list (_menuitem *mi, SDL_Event *event) {
switch (event->type) {
case (SDL_KEYDOWN): /* key was pressed */
if (event->key.keysym.sym == SDLK_LEFT)
menu_focus_prev ();
else if (event->key.keysym.sym == SDLK_RIGHT)
menu_focus_next ();
else if (event->key.keysym.sym == SDLK_UP)
menu_list_select_prev (mi);
else if (event->key.keysym.sym == SDLK_DOWN)
menu_list_select_next (mi);
else if (event->key.keysym.sym == SDLK_RETURN || event->key.keysym.sym == SDLK_RCTRL || event->key.keysym.sym == SDLK_RCTRL)
return 1;
break;
case (SDL_KEYUP):
keybinput_loop (&mi->keybi, event);
menu_draw_entry (mi);
break;
}
return 0;
};