|
|
1.1 root 1: /*
2: Hatari - sdlgui.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: A tiny graphical user interface for Hatari.
8: */
1.1.1.5 ! root 9: const char SDLGui_rcsid[] = "Hatari $Id: sdlgui.c,v 1.18 2008/02/29 20:24:21 thothy Exp $";
1.1 root 10:
11: #include <SDL.h>
12: #include <ctype.h>
13: #include <string.h>
14:
15: #include "main.h"
16: #include "sdlgui.h"
17:
18: #include "font5x8.h"
19: #include "font10x16.h"
20:
21:
1.1.1.2 root 22: static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */
1.1 root 23: static SDL_Surface *pSmallFontGfx = NULL; /* The small font graphics */
24: static SDL_Surface *pBigFontGfx = NULL; /* The big font graphics */
1.1.1.2 root 25: static SDL_Surface *pFontGfx = NULL; /* The actual font graphics */
1.1 root 26: static int fontwidth, fontheight; /* Width & height of the actual font */
27:
28:
29:
30: /*-----------------------------------------------------------------------*/
31: /*
32: Load an 1 plane XBM into a 8 planes SDL_Surface.
33: */
1.1.1.4 root 34: static SDL_Surface *SDLGui_LoadXBM(int w, int h, const Uint8 *pXbmBits)
1.1 root 35: {
1.1.1.5 ! root 36: SDL_Surface *bitmap;
! 37: Uint8 *dstbits;
! 38: const Uint8 *srcbits;
! 39: int x, y, srcpitch;
! 40: int mask;
! 41:
! 42: srcbits = pXbmBits;
! 43:
! 44: /* Allocate the bitmap */
! 45: bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
! 46: if (bitmap == NULL)
! 47: {
! 48: fprintf(stderr, "Failed to allocate bitmap: %s", SDL_GetError());
! 49: return NULL;
! 50: }
! 51:
! 52: srcpitch = ((w + 7) / 8);
! 53: dstbits = (Uint8 *)bitmap->pixels;
! 54: mask = 1;
! 55:
! 56: /* Copy the pixels */
! 57: for (y = 0 ; y < h ; y++)
! 58: {
! 59: for (x = 0 ; x < w ; x++)
! 60: {
! 61: dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0;
! 62: mask <<= 1;
! 63: mask |= (mask >> 8);
! 64: mask &= 0xFF;
! 65: }
! 66: dstbits += bitmap->pitch;
! 67: srcbits += srcpitch;
! 68: }
1.1 root 69:
1.1.1.5 ! root 70: return bitmap;
1.1 root 71: }
72:
73:
74: /*-----------------------------------------------------------------------*/
75: /*
76: Initialize the GUI.
77: */
78: int SDLGui_Init(void)
79: {
1.1.1.5 ! root 80: SDL_Color blackWhiteColors[2] = {{255, 255, 255, 0}, {0, 0, 0, 0}};
1.1 root 81:
1.1.1.5 ! root 82: /* Initialize the font graphics: */
! 83: pSmallFontGfx = SDLGui_LoadXBM(font5x8_width, font5x8_height, font5x8_bits);
! 84: pBigFontGfx = SDLGui_LoadXBM(font10x16_width, font10x16_height, font10x16_bits);
! 85: if (pSmallFontGfx == NULL || pBigFontGfx == NULL)
! 86: {
! 87: fprintf(stderr, "Error: Can not init font graphics!\n");
! 88: return -1;
! 89: }
! 90:
! 91: /* Set color palette of the font graphics: */
! 92: SDL_SetColors(pSmallFontGfx, blackWhiteColors, 0, 2);
! 93: SDL_SetColors(pBigFontGfx, blackWhiteColors, 0, 2);
! 94:
! 95: /* Set font color 0 as transparent: */
! 96: SDL_SetColorKey(pSmallFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
! 97: SDL_SetColorKey(pBigFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
1.1 root 98:
1.1.1.5 ! root 99: return 0;
1.1 root 100: }
101:
102:
103: /*-----------------------------------------------------------------------*/
104: /*
105: Uninitialize the GUI.
106: */
107: int SDLGui_UnInit(void)
108: {
1.1.1.5 ! root 109: if (pSmallFontGfx)
! 110: {
! 111: SDL_FreeSurface(pSmallFontGfx);
! 112: pSmallFontGfx = NULL;
! 113: }
! 114:
! 115: if (pBigFontGfx)
! 116: {
! 117: SDL_FreeSurface(pBigFontGfx);
! 118: pBigFontGfx = NULL;
! 119: }
1.1 root 120:
1.1.1.5 ! root 121: return 0;
1.1 root 122: }
123:
124:
125: /*-----------------------------------------------------------------------*/
126: /*
1.1.1.2 root 127: Inform the SDL-GUI about the actual SDL_Surface screen pointer and
128: prepare the font to suit the actual resolution.
1.1 root 129: */
1.1.1.2 root 130: int SDLGui_SetScreen(SDL_Surface *pScrn)
1.1 root 131: {
1.1.1.5 ! root 132: pSdlGuiScrn = pScrn;
1.1.1.2 root 133:
1.1.1.5 ! root 134: /* Decide which font to use - small or big one: */
! 135: if (pSdlGuiScrn->w >= 640 && pSdlGuiScrn->h >= 400 && pBigFontGfx != NULL)
! 136: {
! 137: pFontGfx = pBigFontGfx;
! 138: }
! 139: else
! 140: {
! 141: pFontGfx = pSmallFontGfx;
! 142: }
! 143:
! 144: if (pFontGfx == NULL)
! 145: {
! 146: fprintf(stderr, "Error: A problem with the font occured!\n");
! 147: return -1;
! 148: }
! 149:
! 150: /* Get the font width and height: */
! 151: fontwidth = pFontGfx->w/16;
! 152: fontheight = pFontGfx->h/16;
1.1 root 153:
1.1.1.5 ! root 154: return 0;
1.1 root 155: }
156:
157:
158: /*-----------------------------------------------------------------------*/
159: /*
160: Center a dialog so that it appears in the middle of the screen.
161: Note: We only store the coordinates in the root box of the dialog,
162: all other objects in the dialog are positioned relatively to this one.
163: */
164: void SDLGui_CenterDlg(SGOBJ *dlg)
165: {
1.1.1.5 ! root 166: dlg[0].x = (pSdlGuiScrn->w/fontwidth-dlg[0].w)/2;
! 167: dlg[0].y = (pSdlGuiScrn->h/fontheight-dlg[0].h)/2;
1.1 root 168: }
169:
170:
171: /*-----------------------------------------------------------------------*/
172: /*
173: Draw a text string.
174: */
175: static void SDLGui_Text(int x, int y, const char *txt)
176: {
1.1.1.5 ! root 177: int i;
! 178: char c;
! 179: SDL_Rect sr, dr;
! 180:
! 181: for (i=0; txt[i]!=0; i++)
! 182: {
! 183: c = txt[i];
! 184: sr.x=fontwidth*(c%16);
! 185: sr.y=fontheight*(c/16);
! 186: sr.w=fontwidth;
! 187: sr.h=fontheight;
! 188: dr.x=x+i*fontwidth;
! 189: dr.y=y;
! 190: dr.w=fontwidth;
! 191: dr.h=fontheight;
! 192: SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr);
! 193: }
1.1 root 194: }
195:
196:
197: /*-----------------------------------------------------------------------*/
198: /*
199: Draw a dialog text object.
200: */
1.1.1.2 root 201: static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum)
1.1 root 202: {
1.1.1.5 ! root 203: int x, y;
! 204: x = (tdlg[0].x+tdlg[objnum].x)*fontwidth;
! 205: y = (tdlg[0].y+tdlg[objnum].y)*fontheight;
! 206: SDLGui_Text(x, y, tdlg[objnum].txt);
1.1 root 207: }
208:
209:
210: /*-----------------------------------------------------------------------*/
211: /*
212: Draw a edit field object.
213: */
1.1.1.2 root 214: static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum)
1.1 root 215: {
1.1.1.5 ! root 216: int x, y;
! 217: SDL_Rect rect;
1.1 root 218:
1.1.1.5 ! root 219: x = (edlg[0].x+edlg[objnum].x)*fontwidth;
! 220: y = (edlg[0].y+edlg[objnum].y)*fontheight;
! 221: SDLGui_Text(x, y, edlg[objnum].txt);
! 222:
! 223: rect.x = x;
! 224: rect.y = y + edlg[objnum].h * fontheight;
! 225: rect.w = edlg[objnum].w * fontwidth;
! 226: rect.h = 1;
! 227: SDL_FillRect(pSdlGuiScrn, &rect, SDL_MapRGB(pSdlGuiScrn->format,160,160,160));
1.1 root 228: }
229:
230:
231: /*-----------------------------------------------------------------------*/
232: /*
233: Draw a dialog box object.
234: */
1.1.1.2 root 235: static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum)
1.1 root 236: {
1.1.1.5 ! root 237: SDL_Rect rect;
! 238: int x, y, w, h, offset;
! 239: Uint32 grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
! 240: Uint32 upleftc, downrightc;
! 241:
! 242: x = bdlg[objnum].x*fontwidth;
! 243: y = bdlg[objnum].y*fontheight;
! 244: if (objnum > 0) /* Since the root object is a box, too, */
! 245: {
! 246: /* we have to look for it now here and only */
! 247: x += bdlg[0].x*fontwidth; /* add its absolute coordinates if we need to */
! 248: y += bdlg[0].y*fontheight;
! 249: }
! 250: w = bdlg[objnum].w*fontwidth;
! 251: h = bdlg[objnum].h*fontheight;
! 252:
! 253: if (bdlg[objnum].state & SG_SELECTED)
! 254: {
! 255: upleftc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
! 256: downrightc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
! 257: }
! 258: else
! 259: {
! 260: upleftc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
! 261: downrightc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
! 262: }
! 263:
! 264: /* The root box should be bigger than the screen, so we disable the offset there: */
! 265: if (objnum != 0)
! 266: offset = 1;
! 267: else
! 268: offset = 0;
! 269:
! 270: /* Draw background: */
! 271: rect.x = x;
! 272: rect.y = y;
! 273: rect.w = w;
! 274: rect.h = h;
! 275: SDL_FillRect(pSdlGuiScrn, &rect, grey);
! 276:
! 277: /* Draw upper border: */
! 278: rect.x = x;
! 279: rect.y = y - offset;
! 280: rect.w = w;
! 281: rect.h = 1;
! 282: SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
! 283:
! 284: /* Draw left border: */
! 285: rect.x = x - offset;
! 286: rect.y = y;
! 287: rect.w = 1;
! 288: rect.h = h;
! 289: SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
! 290:
! 291: /* Draw bottom border: */
! 292: rect.x = x;
! 293: rect.y = y + h - 1 + offset;
! 294: rect.w = w;
! 295: rect.h = 1;
! 296: SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
! 297:
! 298: /* Draw right border: */
! 299: rect.x = x + w - 1 + offset;
! 300: rect.y = y;
! 301: rect.w = 1;
! 302: rect.h = h;
! 303: SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
1.1 root 304: }
305:
306:
307: /*-----------------------------------------------------------------------*/
308: /*
309: Draw a normal button.
310: */
1.1.1.2 root 311: static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum)
1.1 root 312: {
1.1.1.5 ! root 313: int x,y;
1.1 root 314:
1.1.1.5 ! root 315: SDLGui_DrawBox(bdlg, objnum);
1.1 root 316:
1.1.1.5 ! root 317: x = (bdlg[0].x + bdlg[objnum].x + (bdlg[objnum].w-strlen(bdlg[objnum].txt))/2) * fontwidth;
! 318: y = (bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h-1)/2) * fontheight;
1.1 root 319:
1.1.1.5 ! root 320: if (bdlg[objnum].state & SG_SELECTED)
! 321: {
! 322: x+=1;
! 323: y+=1;
! 324: }
! 325: SDLGui_Text(x, y, bdlg[objnum].txt);
1.1 root 326: }
327:
328:
329: /*-----------------------------------------------------------------------*/
330: /*
331: Draw a dialog radio button object.
332: */
1.1.1.2 root 333: static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum)
1.1 root 334: {
1.1.1.5 ! root 335: char str[80];
! 336: int x, y;
1.1 root 337:
1.1.1.5 ! root 338: x = (rdlg[0].x + rdlg[objnum].x) * fontwidth;
! 339: y = (rdlg[0].y + rdlg[objnum].y) * fontheight;
1.1 root 340:
1.1.1.5 ! root 341: if (rdlg[objnum].state & SG_SELECTED)
! 342: str[0]=SGRADIOBUTTON_SELECTED;
! 343: else
! 344: str[0]=SGRADIOBUTTON_NORMAL;
! 345: str[1]=' ';
! 346: strcpy(&str[2], rdlg[objnum].txt);
1.1 root 347:
1.1.1.5 ! root 348: SDLGui_Text(x, y, str);
1.1 root 349: }
350:
351:
352: /*-----------------------------------------------------------------------*/
353: /*
354: Draw a dialog check box object.
355: */
1.1.1.2 root 356: static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum)
1.1 root 357: {
1.1.1.5 ! root 358: char str[80];
! 359: int x, y;
1.1 root 360:
1.1.1.5 ! root 361: x = (cdlg[0].x + cdlg[objnum].x) * fontwidth;
! 362: y = (cdlg[0].y + cdlg[objnum].y) * fontheight;
1.1 root 363:
1.1.1.5 ! root 364: if ( cdlg[objnum].state&SG_SELECTED )
! 365: str[0]=SGCHECKBOX_SELECTED;
! 366: else
! 367: str[0]=SGCHECKBOX_NORMAL;
! 368: str[1]=' ';
! 369: strcpy(&str[2], cdlg[objnum].txt);
1.1 root 370:
1.1.1.5 ! root 371: SDLGui_Text(x, y, str);
1.1 root 372: }
373:
374:
375: /*-----------------------------------------------------------------------*/
376: /*
377: Draw a dialog popup button object.
378: */
1.1.1.2 root 379: static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum)
1.1 root 380: {
1.1.1.5 ! root 381: int x, y, w, h;
! 382: const char *downstr = "\x02";
1.1 root 383:
1.1.1.5 ! root 384: SDLGui_DrawBox(pdlg, objnum);
1.1 root 385:
1.1.1.5 ! root 386: x = (pdlg[0].x + pdlg[objnum].x) * fontwidth;
! 387: y = (pdlg[0].y + pdlg[objnum].y) * fontheight;
! 388: w = pdlg[objnum].w*fontwidth;
! 389: h = pdlg[objnum].h*fontheight;
1.1 root 390:
1.1.1.5 ! root 391: SDLGui_Text(x, y, pdlg[objnum].txt);
! 392: SDLGui_Text(x+w-fontwidth, y, downstr);
1.1 root 393: }
394:
395:
396: /*-----------------------------------------------------------------------*/
397: /*
398: Let the user insert text into an edit field object.
399: NOTE: The dlg[objnum].txt must point to an an array that is big enough
400: for dlg[objnum].w characters!
401: */
402: static void SDLGui_EditField(SGOBJ *dlg, int objnum)
403: {
1.1.1.5 ! root 404: size_t cursorPos; /* Position of the cursor in the edit field */
! 405: int blinkState = 0; /* Used for cursor blinking */
! 406: int bStopEditing = FALSE; /* TRUE if user wants to exit the edit field */
! 407: char *txt; /* Shortcut for dlg[objnum].txt */
! 408: SDL_Rect rect;
! 409: Uint32 grey, cursorCol;
! 410: SDL_Event event;
! 411: int nOldUnicodeMode;
! 412:
! 413: /* Enable unicode translation to get proper characters with SDL_PollEvent */
! 414: nOldUnicodeMode = SDL_EnableUNICODE(TRUE);
! 415:
! 416: grey = SDL_MapRGB(pSdlGuiScrn->format, 192, 192, 192);
! 417: cursorCol = SDL_MapRGB(pSdlGuiScrn->format, 128, 128, 128);
! 418:
! 419: rect.x = (dlg[0].x + dlg[objnum].x) * fontwidth;
! 420: rect.y = (dlg[0].y + dlg[objnum].y) * fontheight;
! 421: rect.w = (dlg[objnum].w + 1) * fontwidth - 1;
! 422: rect.h = dlg[objnum].h * fontheight;
! 423:
! 424: txt = dlg[objnum].txt;
! 425: cursorPos = strlen(txt);
! 426:
! 427: do
! 428: {
! 429: /* Look for events */
! 430: if (SDL_PollEvent(&event) == 0)
! 431: {
! 432: /* No event: Wait some time for cursor blinking */
! 433: SDL_Delay(250);
! 434: blinkState ^= 1;
! 435: }
! 436: else
! 437: {
! 438: /* Handle events */
! 439: do
! 440: {
! 441: switch (event.type)
! 442: {
! 443: case SDL_QUIT: /* User wants to quit */
! 444: bQuitProgram = TRUE;
! 445: bStopEditing = TRUE;
! 446: break;
! 447: case SDL_MOUSEBUTTONDOWN: /* Mouse pressed -> stop editing */
! 448: bStopEditing = TRUE;
! 449: break;
! 450: case SDL_KEYDOWN: /* Key pressed */
! 451: switch (event.key.keysym.sym)
! 452: {
! 453: case SDLK_RETURN:
! 454: case SDLK_KP_ENTER:
! 455: bStopEditing = TRUE;
! 456: break;
! 457: case SDLK_LEFT:
! 458: if (cursorPos > 0)
! 459: cursorPos -= 1;
! 460: break;
! 461: case SDLK_RIGHT:
! 462: if (cursorPos < strlen(txt))
! 463: cursorPos += 1;
! 464: break;
! 465: case SDLK_BACKSPACE:
! 466: if (cursorPos > 0)
! 467: {
! 468: memmove(&txt[cursorPos-1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
! 469: cursorPos -= 1;
! 470: }
! 471: break;
! 472: case SDLK_DELETE:
! 473: if (cursorPos < strlen(txt))
! 474: memmove(&txt[cursorPos], &txt[cursorPos+1], strlen(&txt[cursorPos+1])+1);
! 475: break;
! 476: default:
! 477: /* If it is a "good" key then insert it into the text field */
! 478: if (event.key.keysym.unicode >= 32 && event.key.keysym.unicode < 128
! 479: && event.key.keysym.unicode != PATHSEP)
! 480: {
! 481: if (strlen(txt) < (size_t)dlg[objnum].w)
! 482: {
! 483: memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
! 484: txt[cursorPos] = event.key.keysym.unicode;
! 485: cursorPos += 1;
! 486: }
! 487: }
! 488: break;
! 489: }
! 490: break;
! 491: }
! 492: }
! 493: while (SDL_PollEvent(&event));
! 494:
! 495: blinkState = 1;
! 496: }
! 497:
! 498: /* Redraw the text field: */
! 499: SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw background */
! 500: /* Draw the cursor: */
! 501: if (blinkState && !bStopEditing)
! 502: {
! 503: SDL_Rect cursorrect;
! 504: cursorrect.x = rect.x + cursorPos * fontwidth;
! 505: cursorrect.y = rect.y;
! 506: cursorrect.w = fontwidth;
! 507: cursorrect.h = rect.h;
! 508: SDL_FillRect(pSdlGuiScrn, &cursorrect, cursorCol);
! 509: }
! 510: SDLGui_Text(rect.x, rect.y, dlg[objnum].txt); /* Draw text */
! 511: SDL_UpdateRects(pSdlGuiScrn, 1, &rect);
! 512: }
! 513: while (!bStopEditing);
! 514:
! 515: SDL_EnableUNICODE(nOldUnicodeMode);
1.1 root 516: }
517:
518:
519: /*-----------------------------------------------------------------------*/
520: /*
521: Draw a whole dialog.
522: */
1.1.1.3 root 523: void SDLGui_DrawDialog(const SGOBJ *dlg)
1.1 root 524: {
1.1.1.5 ! root 525: int i;
! 526: for (i = 0; dlg[i].type != -1; i++)
! 527: {
! 528: switch (dlg[i].type)
! 529: {
! 530: case SGBOX:
! 531: SDLGui_DrawBox(dlg, i);
! 532: break;
! 533: case SGTEXT:
! 534: SDLGui_DrawText(dlg, i);
! 535: break;
! 536: case SGEDITFIELD:
! 537: SDLGui_DrawEditField(dlg, i);
! 538: break;
! 539: case SGBUTTON:
! 540: SDLGui_DrawButton(dlg, i);
! 541: break;
! 542: case SGRADIOBUT:
! 543: SDLGui_DrawRadioButton(dlg, i);
! 544: break;
! 545: case SGCHECKBOX:
! 546: SDLGui_DrawCheckBox(dlg, i);
! 547: break;
! 548: case SGPOPUP:
! 549: SDLGui_DrawPopupButton(dlg, i);
! 550: break;
! 551: }
! 552: }
! 553: SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0);
1.1 root 554: }
555:
556:
557: /*-----------------------------------------------------------------------*/
558: /*
559: Search an object at a certain position.
560: */
1.1.1.2 root 561: static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy)
1.1 root 562: {
1.1.1.5 ! root 563: int len, i;
! 564: int ob = -1;
! 565: int xpos, ypos;
! 566:
! 567: len = 0;
! 568: while (dlg[len].type != -1) len++;
! 569:
! 570: xpos = fx / fontwidth;
! 571: ypos = fy / fontheight;
! 572: /* Now search for the object: */
! 573: for (i = len; i >= 0; i--)
! 574: {
! 575: if (xpos >= dlg[0].x+dlg[i].x && ypos >= dlg[0].y+dlg[i].y
! 576: && xpos < dlg[0].x+dlg[i].x+dlg[i].w && ypos < dlg[0].y+dlg[i].y+dlg[i].h)
! 577: {
! 578: ob = i;
! 579: break;
! 580: }
! 581: }
! 582:
! 583: return ob;
! 584: }
! 585:
! 586:
! 587: /*-----------------------------------------------------------------------*/
! 588: /*
! 589: Search a button with a special flag (e.g. SG_DEFAULT or SG_CANCEL).
! 590: */
! 591: static int SDLGui_SearchFlaggedButton(const SGOBJ *dlg, int flag)
! 592: {
! 593: int i = 0;
! 594:
! 595: while (dlg[i].type != -1)
! 596: {
! 597: if (dlg[i].flags & flag)
! 598: return i;
! 599: i++;
! 600: }
1.1 root 601:
1.1.1.5 ! root 602: return 0;
1.1 root 603: }
604:
605:
606: /*-----------------------------------------------------------------------*/
607: /*
608: Show and process a dialog. Returns the button number that has been
1.1.1.2 root 609: pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occured (will be
610: stored in parameter pEventOut).
1.1 root 611: */
1.1.1.2 root 612: int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut)
1.1 root 613: {
1.1.1.5 ! root 614: int obj=0;
! 615: int oldbutton=0;
! 616: int retbutton=0;
! 617: int i, j, b;
! 618: SDL_Event sdlEvent;
! 619: SDL_Rect rct;
! 620: Uint32 grey;
! 621: SDL_Surface *pBgSurface;
! 622: SDL_Rect dlgrect, bgrect;
! 623:
! 624: if (pSdlGuiScrn->h / fontheight < dlg[0].h)
! 625: {
! 626: fprintf(stderr, "Screen size too small for dialog!\n");
! 627: return SDLGUI_ERROR;
! 628: }
! 629:
! 630: grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
! 631:
! 632: dlgrect.x = dlg[0].x * fontwidth;
! 633: dlgrect.y = dlg[0].y * fontheight;
! 634: dlgrect.w = dlg[0].w * fontwidth;
! 635: dlgrect.h = dlg[0].h * fontheight;
! 636:
! 637: bgrect.x = bgrect.y = 0;
! 638: bgrect.w = dlgrect.w;
! 639: bgrect.h = dlgrect.h;
! 640:
! 641: /* Save background */
! 642: pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel,
! 643: pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask);
! 644: if (pSdlGuiScrn->format->palette != NULL)
! 645: {
! 646: SDL_SetColors(pBgSurface, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1);
! 647: }
! 648:
! 649: if (pBgSurface != NULL)
! 650: {
! 651: SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect);
! 652: }
! 653: else
! 654: {
! 655: fprintf(stderr, "SDLGUI_DoDialog: CreateRGBSurface failed: %s\n", SDL_GetError());
! 656: }
! 657:
! 658: /* (Re-)draw the dialog */
! 659: SDLGui_DrawDialog(dlg);
! 660:
! 661: /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
! 662: SDL_PumpEvents();
! 663: b = SDL_GetMouseState(&i, &j);
! 664: obj = SDLGui_FindObj(dlg, i, j);
! 665: if (obj > 0 && (dlg[obj].flags&SG_TOUCHEXIT) )
! 666: {
! 667: oldbutton = obj;
! 668: if (b & SDL_BUTTON(1))
! 669: {
! 670: dlg[obj].state |= SG_SELECTED;
! 671: retbutton = obj;
! 672: }
! 673: }
! 674:
! 675: /* The main loop */
! 676: while (retbutton == 0 && !bQuitProgram)
! 677: {
! 678: if (SDL_WaitEvent(&sdlEvent) == 1) /* Wait for events */
! 679: switch (sdlEvent.type)
! 680: {
! 681: case SDL_QUIT:
! 682: retbutton = SDLGUI_QUIT;
! 683: break;
! 684:
! 685: case SDL_MOUSEBUTTONDOWN:
! 686: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
! 687: {
! 688: /* Not left mouse button -> unsupported event */
! 689: if (pEventOut)
! 690: retbutton = SDLGUI_UNKNOWNEVENT;
! 691: break;
! 692: }
! 693: /* It was the left button: Find the object under the mouse cursor */
! 694: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
! 695: if (obj>0)
! 696: {
! 697: if (dlg[obj].type==SGBUTTON)
! 698: {
! 699: dlg[obj].state |= SG_SELECTED;
! 700: SDLGui_DrawButton(dlg, obj);
! 701: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
! 702: dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
! 703: oldbutton=obj;
! 704: }
! 705: if ( dlg[obj].flags&SG_TOUCHEXIT )
! 706: {
! 707: dlg[obj].state |= SG_SELECTED;
! 708: retbutton = obj;
! 709: }
! 710: }
! 711: break;
! 712:
! 713: case SDL_MOUSEBUTTONUP:
! 714: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
! 715: {
! 716: /* Not left mouse button -> unsupported event */
! 717: if (pEventOut)
! 718: retbutton = SDLGUI_UNKNOWNEVENT;
! 719: break;
! 720: }
! 721: /* It was the left button: Find the object under the mouse cursor */
! 722: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
! 723: if (obj>0)
! 724: {
! 725: switch (dlg[obj].type)
! 726: {
! 727: case SGBUTTON:
! 728: if (oldbutton==obj)
! 729: retbutton=obj;
! 730: break;
! 731: case SGEDITFIELD:
! 732: SDLGui_EditField(dlg, obj);
! 733: break;
! 734: case SGRADIOBUT:
! 735: for (i = obj-1; i > 0 && dlg[i].type == SGRADIOBUT; i--)
! 736: {
! 737: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
! 738: rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
! 739: rct.y = (dlg[0].y+dlg[i].y)*fontheight;
! 740: rct.w = fontwidth;
! 741: rct.h = fontheight;
! 742: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
! 743: SDLGui_DrawRadioButton(dlg, i);
! 744: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 745: }
! 746: for (i = obj+1; dlg[i].type == SGRADIOBUT; i++)
! 747: {
! 748: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
! 749: rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
! 750: rct.y = (dlg[0].y+dlg[i].y)*fontheight;
! 751: rct.w = fontwidth;
! 752: rct.h = fontheight;
! 753: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
! 754: SDLGui_DrawRadioButton(dlg, i);
! 755: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 756: }
! 757: dlg[obj].state |= SG_SELECTED; /* Select this radio button */
! 758: rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
! 759: rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
! 760: rct.w = fontwidth;
! 761: rct.h = fontheight;
! 762: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
! 763: SDLGui_DrawRadioButton(dlg, obj);
! 764: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 765: break;
! 766: case SGCHECKBOX:
! 767: dlg[obj].state ^= SG_SELECTED;
! 768: rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
! 769: rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
! 770: rct.w = fontwidth;
! 771: rct.h = fontheight;
! 772: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
! 773: SDLGui_DrawCheckBox(dlg, obj);
! 774: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 775: break;
! 776: case SGPOPUP:
! 777: dlg[obj].state |= SG_SELECTED;
! 778: SDLGui_DrawPopupButton(dlg, obj);
! 779: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
! 780: dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
! 781: retbutton=obj;
! 782: break;
! 783: }
! 784: }
! 785: if (oldbutton > 0)
! 786: {
! 787: dlg[oldbutton].state &= ~SG_SELECTED;
! 788: SDLGui_DrawButton(dlg, oldbutton);
! 789: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[oldbutton].x)*fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*fontheight-2,
! 790: dlg[oldbutton].w*fontwidth+4, dlg[oldbutton].h*fontheight+4);
! 791: oldbutton = 0;
! 792: }
! 793: if (obj >= 0 && (dlg[obj].flags&SG_EXIT))
! 794: {
! 795: retbutton = obj;
! 796: }
! 797: break;
! 798:
! 799: case SDL_MOUSEMOTION:
! 800: break;
! 801:
! 802: case SDL_KEYDOWN: /* Key pressed */
! 803: if (sdlEvent.key.keysym.sym == SDLK_RETURN
! 804: || sdlEvent.key.keysym.sym == SDLK_KP_ENTER)
! 805: {
! 806: retbutton = SDLGui_SearchFlaggedButton(dlg, SG_DEFAULT);
! 807: }
! 808: else if (sdlEvent.key.keysym.sym == SDLK_ESCAPE)
! 809: {
! 810: retbutton = SDLGui_SearchFlaggedButton(dlg, SG_CANCEL);
! 811: }
! 812: else if (pEventOut)
! 813: {
! 814: retbutton = SDLGUI_UNKNOWNEVENT;
! 815: }
! 816: break;
! 817:
! 818: default:
! 819: if (pEventOut)
! 820: retbutton = SDLGUI_UNKNOWNEVENT;
! 821: break;
! 822: }
! 823: }
! 824:
! 825: /* Restore background */
! 826: if (pBgSurface)
! 827: {
! 828: SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect);
! 829: SDL_FreeSurface(pBgSurface);
! 830: }
! 831:
! 832: /* Copy event data of unsupported events if caller wants to have it */
! 833: if (retbutton == SDLGUI_UNKNOWNEVENT && pEventOut)
! 834: memcpy(pEventOut, &sdlEvent, sizeof(SDL_Event));
1.1.1.2 root 835:
1.1.1.5 ! root 836: if (retbutton == SDLGUI_QUIT)
! 837: bQuitProgram = TRUE;
1.1 root 838:
1.1.1.5 ! root 839: return retbutton;
1.1 root 840: }
841:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.