juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

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 }