ref: 33de2d046acfc7ee42fb71b1804b091f671b098a
parent: a99916512365d68d130c7dfdb3f7ac5e2e0bbe8a
author: rodri <rgl@antares-labs.eu>
date: Wed Sep 20 09:15:48 EDT 2023
more work on the menulist of matches.
--- a/bts.c
+++ b/bts.c
@@ -80,7 +80,7 @@
Ship *curship;
int layoutdone;
Point2 lastshot;
-Matchlist matchlist;
+Menulist *matches;
struct {
int state;
@@ -122,29 +122,6 @@
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 @@
}
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 @@
case Waiting0:
drawtitle(screenb);
drawgameoptions(screenb);
- drawmatchlist(screenb);
+ matches->draw(matches, screenb);
break;
default:
drawboard(screenb, &alienboard);
@@ -803,16 +734,13 @@
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 @@
inittiles();
initboards();
initarmada();
+ matches = newmenulist(14*font->height, "ongoing matches");
game.state = Waiting0;
csetcursor(mctl, &patrolcursor);
--- a/btsd.c
+++ b/btsd.c
@@ -234,14 +234,10 @@
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);
--- a/dat.h
+++ b/dat.h
@@ -108,7 +108,7 @@
typedef struct Mentry Mentry;
typedef struct Mlist Mlist;
-typedef struct Matchlist Matchlist;
+typedef struct Menulist Menulist;
struct Mentry
{
@@ -123,8 +123,15 @@
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*);
};
--- a/fns.h
+++ b/fns.h
@@ -21,3 +21,10 @@
int shiplen(int);
char *shipname(int);
char *statename(int);
+int max(int, int);
+
+/*
+ * menulist
+ */
+Menulist *newmenulist(int, char*);
+void delmenulist(Menulist*);
--- /dev/null
+++ b/menulist.c
@@ -1,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);
+}
--- a/mkfile
+++ b/mkfile
@@ -9,6 +9,7 @@
OFILES=\
alloc.$O\
util.$O\
+ menulist.$O\
HFILES=\
dat.h\
--- a/util.c
+++ b/util.c
@@ -141,3 +141,9 @@
return nil;
return statenametab[state];
}
+
+int
+max(int a, int b)
+{
+ return a > b? a: b;
+}