diff options
-rw-r--r-- | bts.c | 91 | ||||
-rw-r--r-- | btsd.c | 12 | ||||
-rw-r--r-- | dat.h | 13 | ||||
-rw-r--r-- | fns.h | 7 | ||||
-rw-r--r-- | menulist.c | 131 | ||||
-rw-r--r-- | mkfile | 1 | ||||
-rw-r--r-- | util.c | 6 |
7 files changed, 169 insertions, 92 deletions
@@ -80,7 +80,7 @@ Ship armada[NSHIPS]; Ship *curship; int layoutdone; Point2 lastshot; -Matchlist matchlist; +Menulist *matches; struct { int state; @@ -122,29 +122,6 @@ toboard(Board *b, Point p) return np; } -void -addmatch(Mlist *m, int id, char *title) -{ - m->entries = erealloc(m->entries, ++m->nentries * sizeof *m->entries); - m->entries[m->nentries-1] = (Mentry){id, title}; -} - -void -freematchlist(Mlist *m) -{ - int i; - - if(m->entries == nil) - return; - - for(i = 0; i < m->nentries; i++) - free(m->entries[i].title); - free(m->entries); - m->entries = nil; - m->nentries = 0; - m->filling = 0; -} - int rectXarmada(Rectangle r) { @@ -290,52 +267,6 @@ drawgameoptions(Image *dst) } void -drawmatchlist(Image *dst) -{ - Rectangle r, scrollr; - static char title[] = "ongoing matches"; - static char nomatches[] = "no matches"; - int i; - - USED(scrollr); - - if(debug){ - fprint(2, "matchlist entries %p nentries %d filling %d\n", matchlist.entries, matchlist.nentries, matchlist.filling); - for(i = 0; i < matchlist.nentries; i++) - fprint(2, "match id %d title %s\n", matchlist.entries[i].id, matchlist.entries[i].title); - } - - if(matchlist.filling) - return; - - enum { - Vspace = 2, - Scrollwidth = 10, - Maxvisitems = 5, - }; - r.min = Pt(SCRW/2 - stringwidth(font, title)/2, 14*font->height); - r.max = addpt(r.min, Pt(stringwidth(font, title), font->height+Vspace)); - for(i = 0; i < matchlist.nentries; i++) - if(stringwidth(font, matchlist.entries[i].title) > Dx(r)) - r.max.x = r.min.x + stringwidth(font, matchlist.entries[i].title); - - draw(dst, r, display->white, nil, ZP); - string(dst, r.min, display->black, ZP, font, title); - for(i = 0; i < matchlist.nentries; i++){ - r.min.y += font->height+Vspace; - r.max.y = r.min.y + font->height+Vspace; - draw(dst, r, display->white, nil, ZP); - string(dst, r.min, display->black, ZP, font, matchlist.entries[i].title); - } - if(i == 0){ - r.min.y += font->height+Vspace; - r.max.y = r.min.y + font->height+Vspace; - draw(dst, r, display->white, nil, ZP); - string(dst, r.min, display->black, ZP, font, nomatches); - } -} - -void drawinfo(Image *dst) { static Image *c; @@ -405,7 +336,7 @@ redraw(void) case Waiting0: drawtitle(screenb); drawgameoptions(screenb); - drawmatchlist(screenb); + matches->draw(matches, screenb); break; default: drawboard(screenb, &alienboard); @@ -803,16 +734,13 @@ processcmd(char *cmd) chanprint(egress, "id %s\n", uid); else if(nf == 1 && strcmp(f[0], "queued") == 0) game.state = Ready; - else if(!matchlist.filling && nf == 1 && strcmp(f[0], "matches") == 0){ - if(matchlist.nentries > 0) - freematchlist(&matchlist); - matchlist.filling++; - }else if(matchlist.filling && nf == 3) - addmatch(&matchlist, strtoul(f[0], nil, 10), smprint("%s vs %s", f[1], f[2])); - else if(matchlist.filling && nf == 1 && strcmp(f[0], "end") == 0) - matchlist.filling--; - else if(nf == 2 && strcmp(f[0], "no") == 0 && strcmp(f[1], "matches") == 0) - freematchlist(&matchlist); + else if(!matches->filling && nf == 1 && strcmp(f[0], "matches") == 0){ + matches->clear(matches); + matches->filling = 1; + }else if(matches->filling && nf == 3) + matches->add(matches, strtoul(f[0], nil, 10), smprint("%s vs %s", f[1], f[2])); + else if(matches->filling && nf == 1 && strcmp(f[0], "end") == 0) + matches->filling = 0; break; case Ready: if(nf == 1 && strcmp(f[0], "layout") == 0){ @@ -976,6 +904,7 @@ threadmain(int argc, char *argv[]) inittiles(); initboards(); initarmada(); + matches = newmenulist(14*font->height, "ongoing matches"); game.state = Waiting0; csetcursor(mctl, &patrolcursor); @@ -234,14 +234,10 @@ playerproc(void *arg) sendp(playerq, my); else if(nf == 1 && strcmp(f[0], "watch") == 0){ rlock(&theaterlk); - if(theater.next == &theater) - chanprint(my->io.out, "no matches\n"); - else{ - chanprint(my->io.out, "matches\n"); - for(m = theater.next; m != &theater; m = m->next) - chanprint(my->io.out, "%d %s %s\n", m->id, m->pl[0]->name, m->pl[1]->name); - chanprint(my->io.out, "end\n"); - } + chanprint(my->io.out, "matches\n"); + for(m = theater.next; m != &theater; m = m->next) + chanprint(my->io.out, "%d %s %s\n", m->id, m->pl[0]->name, m->pl[1]->name); + chanprint(my->io.out, "end\n"); runlock(&theaterlk); }else if(nf == 2 && strcmp(f[0], "watch") == 0){ mid = strtoul(f[1], nil, 10); @@ -108,7 +108,7 @@ struct Stands typedef struct Mentry Mentry; typedef struct Mlist Mlist; -typedef struct Matchlist Matchlist; +typedef struct Menulist Menulist; struct Mentry { @@ -123,8 +123,15 @@ struct Mlist int filling; }; -struct Matchlist +struct Menulist { Mlist; - int selected; /* [-1,nitems) where -1 is none */ + char *title; + Rectangle r, sr; /* content and scroll rects */ + int high; /* [-1,nitems) where -1 is none */ + + void (*add)(Menulist*, int, char*); + void (*clear)(Menulist*); + void (*update)(Menulist*, Mousectl*); + void (*draw)(Menulist*, Image*); }; @@ -21,3 +21,10 @@ int countshipcells(Map*); int shiplen(int); char *shipname(int); char *statename(int); +int max(int, int); + +/* + * menulist + */ +Menulist *newmenulist(int, char*); +void delmenulist(Menulist*); diff --git a/menulist.c b/menulist.c new file mode 100644 index 0000000..8cd41a8 --- /dev/null +++ b/menulist.c @@ -0,0 +1,131 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <mouse.h> +#include <cursor.h> +#include <keyboard.h> +#include <geometry.h> +#include "dat.h" +#include "fns.h" + +enum { + Menuborder = 2, + Vspace = 2, + Scrollwidth = 10, + Maxvisitems = 5, +}; +static char none[] = "none"; + + +static void +menulist_add(Menulist *ml, int id, char *title) +{ + Mentry e = {id, title}; + int ew; + + ml->entries = erealloc(ml->entries, ++ml->nentries * sizeof *ml->entries); + ml->entries[ml->nentries-1] = e; + + if((ew = stringwidth(font, e.title)) > Dx(ml->r)){ + ml->r.min.x = SCRW/2 - ew/2; + ml->r.max.x = ml->r.min.x + ew; + } + if(ml->nentries > 1) + ml->r.max.y += font->height+Vspace; +} + +static void +menulist_clear(Menulist *ml) +{ + int i, w; + + if(ml->entries == nil) + return; + + for(i = 0; i < ml->nentries; i++) + free(ml->entries[i].title); + free(ml->entries); + ml->entries = nil; + ml->nentries = 0; + ml->filling = 0; + + w = max(stringwidth(font, ml->title), stringwidth(font, none)); + ml->r.min.x = SCRW/2 - w/2; + ml->r.max = addpt(ml->r.min, Pt(w, font->height+Vspace)); + ml->sr = ZR; + ml->high = -1; +} + +static void +menulist_update(Menulist *ml, Mousectl *mc) +{ + if(ptinrect(mc->xy, ml->r)){ + /* item highlighting and selection */ + }else if(ptinrect(mc->xy, ml->sr)){ + /* scrolling */ + } +} + +static void +menulist_draw(Menulist *ml, Image *dst) +{ + static Image *bc; + Rectangle tr, er; /* title and per-entry */ + int i; + + if(ml->filling) + return; + + if(bc == nil) + bc = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); + + /* draw title */ + tr.min = subpt(ml->r.min, Pt(0,Menuborder + font->height+Vspace)); + tr.max = Pt(ml->r.max.x, ml->r.min.y - Menuborder); + draw(dst, tr, display->black, nil, ZP); + string(dst, tr.min, display->white, ZP, font, ml->title); + + /* draw content */ + border(dst, ml->r, -Menuborder, bc, ZP); + er.min = ml->r.min; + er.max = Pt(ml->r.max.x, er.min.y + font->height+Vspace); + for(i = 0; i < ml->nentries; i++){ + draw(dst, er, display->white, nil, ZP); + string(dst, er.min, display->black, ZP, font, ml->entries[i].title); + er.min.y += font->height+Vspace; + er.max.y = er.min.y + font->height+Vspace; + } + if(i == 0){ + draw(dst, er, display->white, nil, ZP); + string(dst, er.min, display->black, ZP, font, none); + } +} + +Menulist * +newmenulist(int topmargin, char *title) +{ + Menulist *ml; + int w; + + ml = emalloc(sizeof *ml); + memset(ml, 0, sizeof *ml); + ml->title = estrdup(title); + w = max(stringwidth(font, title), stringwidth(font, none)); + ml->r.min = Pt(SCRW/2 - w/2, topmargin); + ml->r.max = addpt(ml->r.min, Pt(w, font->height+Vspace)); + ml->high = -1; + ml->add = menulist_add; + ml->clear = menulist_clear; + ml->update = menulist_update; + ml->draw = menulist_draw; + return ml; +} + +void +delmenulist(Menulist *ml) +{ + ml->clear(ml); + free(ml->title); + free(ml); +} @@ -9,6 +9,7 @@ TARG=\ OFILES=\ alloc.$O\ util.$O\ + menulist.$O\ HFILES=\ dat.h\ @@ -141,3 +141,9 @@ statename(int state) return nil; return statenametab[state]; } + +int +max(int a, int b) +{ + return a > b? a: b; +} |