gfxform.c (3622B)
1 /* gfxform.c - formularios (menus de la app) en pixeles. */ 2 #include <string.h> 3 #include "gfx.h" 4 #include "form.h" 5 6 int (*gfx_form_backdrop)(Surface *s, bool compact); 7 8 void gfx_box(Surface *s, int x, int y, int w, int h, Color bg, Color border) 9 { 10 gfx_rect(s, x, y, w, h, bg); 11 gfx_frame(s, x, y, w, h, border); 12 } 13 14 int gfx_text_center(Surface *s, const Font *f, int x, int y, int w, const char *t, Color c) 15 { 16 int tw = gfx_text_w(f, t); 17 if (tw > w) return gfx_text_fit(s, f, x, y, w, t, c); 18 return gfx_text(s, f, x + (w - tw) / 2, y, t, c); 19 } 20 21 Color gfx_dim(Color c) 22 { 23 int r = (c >> 11) & 31, g = (c >> 5) & 63, b = c & 31; 24 return (Color)(((r / 2) << 11) | ((g / 2) << 5) | (b / 2)); 25 } 26 27 static void cat(char *buf, int n, const char *s) { int p = (int)strlen(buf); str_put(buf, n, p, s); } 28 29 void gfx_form(Surface *s, const struct Form *f, HitList *hits) 30 { 31 if (hits) hits->n = 0; 32 int W = s->w, H = s->h; 33 bool compact = W < 400; 34 int top; 35 if (gfx_form_backdrop) top = gfx_form_backdrop(s, compact); 36 else { gfx_rect(s, 0, 0, W, H, RGB(20, 24, 32)); top = compact ? 8 : 24; } 37 int rowh = compact ? 13 : 16; 38 int shown = 0; 39 for (int i = 0; i < f->n; i++) if (!f->f[i].hidden) shown++; 40 int w = compact ? W - 16 : 420, h = 28 + shown * rowh + 22; 41 int x = (W - w) / 2, y = top; 42 if (y + h > H - 12) y = H - 12 - h; 43 gfx_box(s, x, y, w, h, C_PANEL, C_ACCENT); 44 gfx_rect(s, x, y, w, 16, C_ACCENT); 45 gfx_text_fit(s, &font_bold, x + 6, y + 2, w - 12, f->title, C_OUTLINE); 46 int ly = y + 24, lw = compact ? 120 : 170; 47 for (int i = 0; i < f->n; i++) { 48 const Field *fd = &f->f[i]; 49 if (fd->hidden) continue; 50 bool sel = i == f->cur; 51 switch (fd->type) { 52 case F_LABEL: 53 gfx_text_fit(s, &font_small, x + 8, ly + 2, w - 16, fd->label, C_DIM); 54 break; 55 case F_BUTTON: 56 if (sel) gfx_rect(s, x + 4, ly - 2, w - 8, rowh - 1, C_ACCENT); 57 gfx_text_fit(s, sel ? &font_bold : &font_normal, x + 10, ly, w - 20, fd->label, 58 sel ? C_OUTLINE : fd->disabled ? C_DIM : C_TEXT); 59 break; 60 case F_CHOICE: { 61 gfx_text_fit(s, &font_normal, x + 10, ly, lw - 12, fd->label, sel ? C_ACCENT : C_TEXT); 62 if (sel) gfx_rect(s, x + lw, ly - 2, w - lw - 6, rowh - 1, C_ACCENT); 63 char buf[64] = "< "; 64 cat(buf, sizeof buf, fd->nchoices ? fd->choices[fd->value] : ""); 65 cat(buf, sizeof buf, " >"); 66 gfx_text_fit(s, sel ? &font_bold : &font_normal, x + lw + 4, ly, w - lw - 12, buf, sel ? C_OUTLINE : C_TEXT); 67 break; 68 } 69 case F_TEXT: 70 gfx_text_fit(s, &font_normal, x + 10, ly, lw - 12, fd->label, sel ? C_ACCENT : C_TEXT); 71 gfx_rect(s, x + lw, ly - 2, w - lw - 6, rowh - 1, sel ? C_PANEL2 : RGB(40, 44, 56)); 72 if (sel) gfx_frame(s, x + lw, ly - 2, w - lw - 6, rowh - 1, C_ACCENT); 73 { 74 int tw = gfx_text_fit(s, &font_normal, x + lw + 4, ly, w - lw - 16, fd->text, C_WHITE); 75 if (sel) gfx_rect(s, x + lw + 4 + tw, ly, 6, 11, C_ACCENT); 76 } 77 break; 78 } 79 hit_add(hits, x + 2, ly - 2, w - 4, rowh, HIT_APP, i); 80 ly += rowh; 81 } 82 if (f->msg[0]) gfx_text_fit(s, &font_normal, x + 8, y + h - 16, w - 16, f->msg, f->msg_err ? C_ERR : C_OK); 83 gfx_text_fit(s, &font_small, 4, H - 9, W - 8, 84 g_lang ? "Up/Down move, Left/Right change, Enter select, Esc back" : "Arriba/Abajo mover, Izq/Der cambiar, Enter elegir, Esc volver", C_TEXT); 85 }